Implements skin_import into a running server

This commit is contained in:
AliasAlreadyTaken 2024-07-23 21:25:48 +02:00
parent c820215341
commit 654e63cbc5
12 changed files with 152 additions and 168 deletions

View File

@ -3,7 +3,10 @@ allow_defined_top = true
globals = { globals = {
"minetest", "minetest",
"core" "core",
-- We need to overwrite a function of the skins namespace
"skins"
} }
read_globals = { read_globals = {
@ -15,6 +18,5 @@ read_globals = {
"dump", "DIR_DELIM", "VoxelArea", "Settings", "dump", "DIR_DELIM", "VoxelArea", "Settings",
-- MTG -- MTG
"default", "sfinv", "creative", "default", "sfinv", "creative"
"skins"
} }

View File

@ -1,19 +0,0 @@
local chatcommand_cmd = "admin_example"
local chatcommand_definition = {
params = yl_skinsdb_addon.t("chatcommand_admin_parameters"), -- Short parameter description
description = yl_skinsdb_addon.t("chatcommand_admin_description"), -- Full description
privs = {[yl_skinsdb_addon.settings.admin_priv] = true}, -- Require the "privs" privilege to run
func = function(name, param)
local success = true
if success then
return true, yl_skinsdb_addon.t("chatcommand_admin_success_message")
else
return false, yl_skinsdb_addon.t("chatcommand_admin_fail_message")
end
end
-- Called when command is run. Returns boolean success and text output.
-- Special case: The help message is shown to the player if `func`
-- returns false without a text output.
}
minetest.register_chatcommand(chatcommand_cmd, chatcommand_definition)

View File

@ -0,0 +1,18 @@
local chatcommand_cmd = "import_skins"
local chatcommand_definition = {
params = yl_skinsdb_addon.t("chatcommand_import_skins_parameters"),
description = yl_skinsdb_addon.t("chatcommand_import_skins_description"),
privs = {[yl_skinsdb_addon.settings.admin_priv] = true},
func = function(name, param)
local success, message = yl_skinsdb_addon.load_skins(
yl_skinsdb_addon.settings.path_textures,
yl_skinsdb_addon.callback_dam)
if success then
return true, message
else
return false, message
end
end
}
minetest.register_chatcommand(chatcommand_cmd, chatcommand_definition)

View File

@ -1,2 +1 @@
dofile(yl_skinsdb_addon.modpath .. "chatcommand_admin.lua") dofile(yl_skinsdb_addon.modpath .. "chatcommand_import_skins.lua")
dofile(yl_skinsdb_addon.modpath .. "chatcommand_player.lua")

View File

@ -1,14 +1,11 @@
-- Setting a configuration, switch the order in which the settings shall take precedence. First valid one taken. -- Setting a configuration, switch the order in which the settings shall take precedence. First valid one taken.
yl_skinsdb_addon.settings = {} yl_skinsdb_addon.settings = {}
yl_skinsdb_addon.settings.path_textures = minetest.settings:get( yl_skinsdb_addon.settings.debug = true
"yl_skinsdb_addon.save_path") or
"worldmods/yl_skins_folder/textures"
yl_skinsdb_addon.settings.path_meta = minetest.settings:get( yl_skinsdb_addon.settings.path_textures =
"yl_skinsdb_addon.save_path") or minetest.settings:get("yl_skinsdb_addon.save_path") or "yl_skins/textures"
"worldmods/yl_skins_folder/meta"
yl_skinsdb_addon.settings.admin_privs = minetest.settings:get( yl_skinsdb_addon.settings.admin_priv = minetest.settings:get(
"yl_skinsdb_addon.admin_privs") or "yl_skinsdb_addon.admin_privs") or
"server" "server"

View File

@ -1,11 +1,45 @@
This is a skinsDB addon, in a stub, to not infect the rest of our code with GPL. This is a skinsDB addon, in a stub, to not infect the rest of our code with GPL.
The only functionality this mod is intended to add is a way to retrofit skins into a running server. This mod allows to add skins from a folder that is not the textures folder of skinsDB: done
THis mod also allows to retrofit skins into a running server
We need We need
- a process to clone, push to and update this mod on the server - a folder in the world folder that holds all the textures. By default yl_skins
- a second mod that holds all the textures
- a chatcommand that reads the files of a directory, compares them to a list we have ingame and then adds new skins to a table, which is then processed by - a chatcommand that reads the files of a directory, compares them to a list we have ingame and then adds new skins to a table, which is then processed by
- a function that actually imports those skins and makes them available to players - a function that actually imports those skins and makes them available to players
- The same function can be used at serverstart to transmit the skins and make them available
###
2024-07-20 08:31:07: ERROR[Main]: ServerError: AsyncErr: Lua: Runtime error from mod 'yl_skinsdb_addon' in callback on_chat_message(): ...5.9.0/minetest-dev/bin/../mods/skinsdb/skin_meta_api.lua:62: attempt to concatenate a nil value
2024-07-20 08:31:07: ERROR[Main]: stack traceback:
2024-07-20 08:31:07: ERROR[Main]: ...5.9.0/minetest-dev/bin/../mods/skinsdb/skin_meta_api.lua:62: in function 'set_hand_from_texture'
2024-07-20 08:31:07: ERROR[Main]: ...test/5.9.0/minetest-dev/bin/../mods/skinsdb/skinlist.lua:83: in function 'register_skin'
2024-07-20 08:31:07: ERROR[Main]: ...lds/Minetest_dev/worldmods/yl_skinsdb_addon/internal.lua:35: in function 'load_skins'
2024-07-20 08:31:07: ERROR[Main]: .../worldmods/yl_skinsdb_addon/chatcommand_import_skins.lua:8: in function 'func'
2024-07-20 08:31:07: ERROR[Main]: ...minetest-dev/bin/../builtin/profiler/instrumentation.lua:124: in function 'func'
2024-07-20 08:31:07: ERROR[Main]: ...minetest/5.9.0/minetest-dev/bin/../builtin/game/chat.lua:79: in function <...minetest/5.9.0/minetest-dev/bin/../builtin/game/chat.lua:52>
2024-07-20 08:31:07: ERROR[Main]: ...st/5.9.0/minetest-dev/bin/../builtin/common/register.lua:26: in function <...st/5.9.0/minetest-dev/bin/../builtin/common/register.lua:12>
###
2024-07-20 09:05:52: ACTION[Main]: core.get_current_modname()="skinsdb"
2024-07-20 09:05:52: ACTION[Main]: self._texture="player.LeetPeet.0.png"
2024-07-20 09:05:52: ACTION[Main]: self._texture:gsub('[%p%c%s]', '')="playerLeetPeet0png"
2024-07-20 09:05:52: ACTION[Main]: core.get_current_modname()="skinsdb"
2024-07-20 09:05:52: ACTION[Main]: self._texture="character.warrior_m2.png"
2024-07-20 09:05:52: ACTION[Main]: self._texture:gsub('[%p%c%s]', '')="characterwarriorm2png"
2024-07-20 09:05:52: ACTION[Main]: core.get_current_modname()="skinsdb"
2024-07-20 09:05:52: ACTION[Main]: self._texture="player.AstronomiCow.0.png"
2024-07-20 09:05:52: ACTION[Main]: self._texture:gsub('[%p%c%s]', '')="playerAstronomiCow0png"
2024-07-20 09:05:52: ACTION[Main]: core.get_current_modname()="skinsdb"
2024-07-20 09:05:52: ACTION[Main]: self._texture="player.Dragoni_is_bored.0.png"
2024-07-20 09:05:52: ACTION[Main]: self._texture:gsub('[%p%c%s]', '')="playerDragoniisbored0png"
2024-07-20 09:05:52: ACTION[Main]: core.get_current_modname()="skinsdb"
2024-07-20 09:05:52: ACTION[Main]: self._texture="player.ElishQa.0.png"
2024-07-20 09:05:52: ACTION[Main]: self._texture:gsub('[%p%c%s]', '')="playerElishQa0png"
2024-07-20 09:05:52: ACTION[Main]: core.get_current_modname()="skinsdb"
2024-07-20 09:05:52: ACTION[Main]: self._texture="player.Athena.0.png"
2024-07-20 09:05:52: ACTION[Main]: self._texture:gsub('[%p%c%s]', '')="playerAthena0png"

View File

@ -18,11 +18,10 @@ dofile(yl_skinsdb_addon.modpath .. "texts.lua")
dofile(yl_skinsdb_addon.modpath .. "information.lua") dofile(yl_skinsdb_addon.modpath .. "information.lua")
dofile(yl_skinsdb_addon.modpath .. "config.lua") dofile(yl_skinsdb_addon.modpath .. "config.lua")
--dofile(yl_skinsdb_addon.modpath .. "setup.lua") --dofile(yl_skinsdb_addon.modpath .. "setup.lua")
--dofile(yl_skinsdb_addon.modpath .. "privs.lua") dofile(yl_skinsdb_addon.modpath .. "overwrite.lua")
dofile(yl_skinsdb_addon.modpath .. "internal.lua") dofile(yl_skinsdb_addon.modpath .. "internal.lua")
--dofile(yl_skinsdb_addon.modpath .. "api.lua")
dofile(yl_skinsdb_addon.modpath .. "initialize.lua") dofile(yl_skinsdb_addon.modpath .. "initialize.lua")
--dofile(yl_skinsdb_addon.modpath .. "chatcommands.lua") dofile(yl_skinsdb_addon.modpath .. "chatcommands.lua")
local mod_end_time = (minetest.get_us_time() - mod_start_time) / 1000000 local mod_end_time = (minetest.get_us_time() - mod_start_time) / 1000000
minetest.log("action", "[MOD] yl_skinsdb_addon loaded in [" .. mod_end_time .. "s]") minetest.log("action", "[MOD] yl_skinsdb_addon loaded in [" .. mod_end_time .. "s]")

View File

@ -1,8 +1,7 @@
-- Use this file to initialize variables once after server start and check everything is in place -- Use this file to initialize variables once after server start and check everything is in place
local function run_each_serverstart() local function run_each_serverstart()
yl_skinsdb_addon.data = {} yl_skinsdb_addon.data = {}
yl_skinsdb_addon.load_skins(yl_skinsdb_addon.settings.path_textures, yl_skinsdb_addon.load_skins(yl_skinsdb_addon.settings.path_textures)
yl_skinsdb_addon.settings.path_meta)
end end
run_each_serverstart() run_each_serverstart()

View File

@ -1,137 +1,81 @@
-- The functions and variables in this file are only for use in the mod itself. -- The functions and variables in this file are only for use in the mod itself.
-- Those that do real work should be local and wrapped in public functions -- Those that do real work should be local and wrapped in public functions
local function log(text) local function log(text)
local logmessage = yl_skinsdb_addon.t("log_prefix", yl_skinsdb_addon.modname, text) local logmessage = yl_skinsdb_addon.t("log_prefix",
if yl_skinsdb_addon.settings.debug then minetest.log("action", logmessage) end yl_skinsdb_addon.modname, text)
if yl_skinsdb_addon.settings.debug then
minetest.log("action", logmessage)
end
return logmessage return logmessage
end end
function yl_skinsdb_addon.log(text) return log(text) end function yl_skinsdb_addon.log(text) return log(text) end
--[[ local function load_skins(path_textures, callback_dam)
-- Load skins from the current mod directory
local path_skins = yl_skinsdb_addon.worldpath .. path_textures
local dir_list = minetest.get_dir_list(path_skins)
local imported_skins_list = {}
local success
local good, bad, total = 0, 0, 0
local function get_savepath() if (not next(dir_list)) then
local savepath = yl_skinsdb_addon.worldpath .. yl_skinsdb_addon.settings.save_path log("Skins not found in " .. dump(path_skins))
log(yl_skinsdb_addon.t("log_prefix", dump(savepath))) return false, "Skins not found in " .. dump(path_skins)
return savepath
end
local function get_filepath(filename)
local path_to_file = get_savepath() .. DIR_DELIM .. filename .. ".json"
log(yl_skinsdb_addon.t("get_filepath", dump(filename), dump(path_to_file)))
return path_to_file
end
local function save_json(filename, content)
if type(filename) ~= "string" or type(content) ~= "table" then
return false
end
local savepath = get_filepath(filename)
local savecontent = minetest.write_json(content)
return minetest.safe_file_write(savepath, savecontent)
end
local function load_json(path)
local file = io.open(path, "r")
if not file then
return false, yl_skinsdb_addon.t("error_cannot_open_file", dump(path))
end end
local content = file:read("*all") for _, filename in pairs(dir_list) do
file:close() if (yl_skinsdb_addon.data[filename] == nil) then
local dam_options = {filepath = path_skins .. DIR_DELIM .. filename}
if not content then yl_skinsdb_addon.data[filename] = true
return false, yl_skinsdb_addon.t("error_cannot_read_file", dump(path)) local success_dam = minetest.dynamic_add_media(dam_options,
end callback_dam)
-- TODO: Either move everything below to the callback OR
return true, minetest.parse_json(content) -- evne worse, only go on after each file was delivered to each player
end -- That means having a file of players and marking each as "received"
-- only after the last player got the file, make the skin happen
-- Public functions wrap the private ones, so they can be exchanged easily local success_rs, message_rs =
skins.register_skin(path_skins, filename)
function yl_skinsdb_addon.load(filename, ...) return load_json(filename, ...) end if success_rs == true then
imported_skins_list[filename] = "import"
function yl_skinsdb_addon.save(filename, content, ...) log("Added skin " .. dump(filename))
return save_json(filename, content, ...) good = good + 1
end
]] --
-- Load skins
--
function yl_skinsdb_addon.load_skins(textures, meta)
local path_textures = yl_skinsdb_addon.worldpath .. textures
local path_meta = yl_skinsdb_addon.worldpath .. meta
local skins_dir_list = minetest.get_dir_list(path_textures)
for _, fn in pairs(skins_dir_list) do
local name, sort_id, is_preview, playername
local nameparts = string.gsub(fn, "[.]", skins.fsep):split(skins.fsep)
-- check allowed prefix and file extension
if (nameparts[1] == 'player' or nameparts[1] == 'character') and
nameparts[#nameparts]:lower() == 'png' then
-- cut filename extension
table.remove(nameparts, #nameparts)
-- check preview suffix
if nameparts[#nameparts] == 'preview' then
is_preview = true
table.remove(nameparts, #nameparts)
end
-- Build technically skin name
name = table.concat(nameparts, '_')
-- Handle metadata from file name
if not is_preview then
-- Get player name
if nameparts[1] == "player" then
playername = nameparts[2]
table.remove(nameparts, 1)
sort_id = 0
else
sort_id = 5000
end
-- Get sort index
if tonumber(nameparts[#nameparts]) then
sort_id = sort_id + nameparts[#nameparts]
end
end
local skin_obj = skins.get(name) or skins.new(name)
if is_preview then
skin_obj:set_preview(fn)
else else
skin_obj:set_texture(fn) imported_skins_list[filename] = "noimport"
skin_obj:set_meta("_sort_id", sort_id) log("Cannot add skin " .. dump(filename) .. " Reason: " ..
if playername then dump(message_rs))
skin_obj:set_meta("assignment", "player:" .. playername) bad = bad + 1
skin_obj:set_meta("playername", playername)
end
local file = io.open(path_textures .. DIR_DELIM .. fn, "r")
local skin_format = skins.get_skin_format(file)
skin_obj:set_meta("format", skin_format)
file:close()
skin_obj:set_hand_from_texture()
file = io.open(path_meta .. DIR_DELIM .. name .. ".txt", "r")
if file then
local data = string.split(file:read("*all"), "\n", 3)
file:close()
skin_obj:set_meta("name", data[1])
skin_obj:set_meta("author", data[2])
skin_obj:set_meta("license", data[3])
else
-- remove player / character prefix if further naming given
if nameparts[2] and not tonumber(nameparts[2]) then
table.remove(nameparts, 1)
end
skin_obj:set_meta("name", table.concat(nameparts, ' '))
end
end end
else
imported_skins_list[filename] = "exists"
log("Cannot add skin " .. dump(filename) .. " already exists.")
bad = bad + 1
end
total = total + 1
end
local return_message = "Total: " .. tostring(total) .. ", good: " ..
tostring(good) .. ", bad: " .. tostring(bad) ..
"\n"
for k, state in pairs(imported_skins_list) do
if (state == "import") then
return_message = return_message .. "Import success: " .. k .. "\n"
elseif (state == "noimport") then
return_message = return_message .. "Import failed: " .. k .. "\n"
end end
end end
if (good > 0) then
success = true
else
success = false
end
return success, return_message
end end
function yl_skinsdb_addon.load_skins(path_textures, callback)
return load_skins(path_textures, callback)
end
function yl_skinsdb_addon.callback_dam(name) log("Adds skin for " .. dump(name)) end

View File

@ -1,5 +1,5 @@
name = yl_skinsdb_addon name = yl_skinsdb_addon
description = An addon to skinsdb to retrofit skins description = An addon to skinsdb to retrofit skins
depends = skinsdb, yl_skins_folder depends = skinsdb
author = AliasAlreadyTaken author = AliasAlreadyTaken
title = YL Skins Addon title = YL SkinsDB Addon

11
overwrite.lua Normal file
View File

@ -0,0 +1,11 @@
local skins = skins.skin_class
local old_skins_skin_class_set_hand_from_texture = skins.set_hand_from_texture
function skins:set_hand_from_texture()
if (core.get_current_modname() ~= nil) then
return old_skins_skin_class_set_hand_from_texture(self)
end
-- local hand = core.get_current_modname()..':'..self._texture:gsub('[%p%c%s]', '')
-- local hand = "skinsdb:playerLeetPeet0png"
-- self:set_hand(hand)
end

View File

@ -15,10 +15,10 @@ texts["get_filepath"] = "get_filepath : @1"
texts["information_additional"] = "An addon to skinsdb to retrofit skins" texts["information_additional"] = "An addon to skinsdb to retrofit skins"
texts["chatcommand_admin_description"] = "Admin Chatcommand description" texts["chatcommand_import_skins_parameters"] = "Admin Chatcommand description"
texts["chatcommand_admin_parameters"] = "<name> <privilege>" texts["chatcommand_import_skins_description"] = "<name> <privilege>"
texts["chatcommand_admin_success_message"] = "Sucess message" texts["chatcommand_import_skins_success_message"] = "Sucess message"
texts["chatcommand_admin_fail_message"] = "Fail message" texts["chatcommand_import_skins_fail_message"] = "Fail message"
texts["chatcommand_player_description"] = "Player Chatcommand description" texts["chatcommand_player_description"] = "Player Chatcommand description"
texts["chatcommand_player_parameters"] = "<name> <privilege>" texts["chatcommand_player_parameters"] = "<name> <privilege>"