Skip to content

Commit

Permalink
Revert "Update skinsdb from upstream."
Browse files Browse the repository at this point in the history
This reverts commit 81c577e.
  • Loading branch information
dacmot committed Jul 18, 2024
1 parent 4840a50 commit 9743d72
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 285 deletions.
2 changes: 1 addition & 1 deletion builder/mods_src/player/skinsdb
25 changes: 0 additions & 25 deletions mods/player/skinsdb/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,6 @@ Get all allowed skins for player. All public and all player's private skins. If
Get all skins with metadata key is set to value. Example:
skins.get_skinlist_with_meta("playername", playername) - Get all private skins (w.o. public) for playername

## skins.register_skin(path, filename)
Registers a new skin based on the texture file path specified by `path` and `filename`.

* `path` (string): points to the parent directory of the texture `filename`.
Generally, this should be in the format `mymod.modpath .. "/textures"`.
* `filename` (string): full file name, without any path specifications.
The file name must adhere to [one of the accepted naming formats](textures/readme.txt).

Note: this function takes the following files into consideration:

1. `<path>/<filename>` (required)
* Main skin texture
2. `<path>/<filenamestem><separator>preview.png` (optional)
* Pre-generated preview image
3. `<path>/../meta/<filenamestem>.txt` (optional)
* Metadata regarding the skin

Return values:

* On failure: `false, reason`
* `reason` (string): human readable reason string (similar to `io.open` errors)
* On success: `true, key`
* `key`: unique skins key for use with e.g. `skins.get(key)` for subsequent
fine-tuning of the skin registration.


## skins.new(key, object)
Create and register a new skin object for given key
Expand Down
18 changes: 3 additions & 15 deletions mods/player/skinsdb/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,14 @@
local storage = minetest.get_mod_storage()

function skins.get_player_skin(player)
local player_name = player:get_player_name()
local meta = player:get_meta()
if meta:get("skinsdb:skin_key") then
-- Move player data prior July 2018 to mod storage
storage:set_string(player_name, meta:get_string("skinsdb:skin_key"))
storage:set_string(player:get_player_name(), meta:get_string("skinsdb:skin_key"))
meta:set_string("skinsdb:skin_key", "")
end

local skin_name = storage:get_string(player_name)
local skin = skins.get(skin_name)
if #skin_name > 0 and not skin then
-- Migration step to convert `_`-delimited skins to `.` (if possible)
skin = skins.__fuzzy_match_skin_name(player_name, skin_name, true)
if skin then
storage:set_string(player_name, skin:get_key())
else
storage:set_string(player_name, "")
end
end
return skin or skins.get(skins.default)
local skin = storage:get_string(player:get_player_name())
return skins.get(skin) or skins.get(skins.default)
end

-- Assign skin to player
Expand Down
9 changes: 6 additions & 3 deletions mods/player/skinsdb/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ skins = {}
skins.modpath = minetest.get_modpath(minetest.get_current_modname())
skins.default = "character"

-- see skindsdb/textures/readme.txt to avoid playername with underscore problem
skins.fsep = minetest.settings:get("skinsdb_fsep") or "_"
if skins.fsep == "_" then
minetest.log("warning", "skinsdb filename seperator is set to " .. skins.fsep .. ", see skindsdb/textures/readme.txt to avoid problems with playernames containing underscore")
end

dofile(skins.modpath.."/skin_meta_api.lua")
dofile(skins.modpath.."/api.lua")
dofile(skins.modpath.."/skinlist.lua")
Expand Down Expand Up @@ -111,6 +117,3 @@ minetest.register_allow_player_inventory_action(function(player, action, inv, da
return 0
end
end)

--dofile(skins.modpath.."/unittest.lua")

3 changes: 3 additions & 0 deletions mods/player/skinsdb/settingtypes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# texture filename seperator, default "_"
# see skindsdb/textures/readme.txt to avoid playername with underscore problem
skinsdb_fsep (texture filename seperator) enum _ _,.
196 changes: 60 additions & 136 deletions mods/player/skinsdb/skinlist.lua
Original file line number Diff line number Diff line change
@@ -1,148 +1,72 @@
local dbgprint = false and print or function() end
local skins_dir_list = minetest.get_dir_list(skins.modpath.."/textures")

--- @param path Path to the "textures" directory, without tailing slash.
--- @param filename Current file name, such as "player.groot.17.png".
--- @return On error: false, error message. On success: true, skin key
function skins.register_skin(path, filename)
-- See "textures/readme.txt" for allowed formats
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)

local prefix, sep, identifier, extension = filename:match("^(%a+)([_.])([%w_.]+)%.(%a+)$")
--[[
prefix: "character" or "player"
sep: "." (new) or "_" (legacy)
identifier: number, name or (name + sep + number)
^ previews are explicity skipped
extension: "png" only due `skins.get_skin_format`
]]
-- check allowed prefix and file extension
if (nameparts[1] == 'player' or nameparts[1] == 'character') and
nameparts[#nameparts]:lower() == 'png' then

-- Filter out files that do not match the allowed patterns
if not extension or extension:lower() ~= "png" then
return false, "invalid skin name"
end
if prefix ~= "player" and prefix ~= "character" then
return false, "unknown type"
end

local preview_suffix = sep .. "preview"
if identifier:sub(-#preview_suffix) == preview_suffix then
-- The preview texture is added by the main skin texture (if exists)
return false, "preview texture"
end

assert(path)
if path == ":UNITTEST:" then
path = nil
end

dbgprint("Found skin", prefix, identifier, extension)

local sort_id -- number, sorting "rank" in the skin list
local playername -- string, if player-specific
if prefix == "player" then
-- Allow "player.PLAYERNAME.png" and "player.PLAYERNAME.123.png"
local splits = identifier:split(sep)

playername = splits[1]
-- Put in front
sort_id = 0 + (tonumber(splits[2]) or 0)
-- cut filename extension
table.remove(nameparts, #nameparts)

if #splits > 1 and sep == "_" then
minetest.log("warning", "skinsdb: The skin name '" .. filename .. "' is ambigous." ..
" Please use the separator '.' to lock it down to the correct player name.")
-- check preview suffix
if nameparts[#nameparts] == 'preview' then
is_preview = true
table.remove(nameparts, #nameparts)
end
else -- Public skin "character*"
-- Less priority
sort_id = 5000 + (tonumber(identifier) or 0)
end

local filename_noext = prefix .. sep .. identifier

dbgprint("Register skin", filename_noext, playername, sort_id)

-- Register skin texture
local skin_obj = skins.get(filename_noext) or skins.new(filename_noext)
skin_obj:set_texture(filename)
skin_obj:set_meta("_sort_id", sort_id)
if sep ~= "_" then
skin_obj._legacy_name = filename_noext:gsub("[._]+", "_")
end

if playername then
skin_obj:set_meta("assignment", "player:"..playername)
skin_obj:set_meta("playername", playername)
end

if path then
-- Get type of skin based on dimensions
local file = io.open(path .. "/" .. filename, "r")
local skin_format = skins.get_skin_format(file)
skin_obj:set_meta("format", skin_format)
file:close()
end

skin_obj:set_hand_from_texture()
skin_obj:set_meta("name", identifier)

if path then
-- Optional skin information
local file = io.open(path .. "/../meta/" .. filename_noext .. ".txt", "r")
if file then
dbgprint("Found meta")
local data = string.split(file:read("*all"), "\n", 3)
skin_obj:set_meta("name", data[1])
skin_obj:set_meta("author", data[2])
skin_obj:set_meta("license", data[3])
-- 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
end

if path then
-- Optional preview texture
local preview_name = filename_noext .. sep .. "preview.png"
local fh = io.open(path .. "/" .. preview_name)
if fh then
dbgprint("Found preview", preview_name)
skin_obj:set_preview(preview_name)
end
end

return true, skin_obj:get_key()
end

--- Internal function. Fallback/migration code for `.`-delimited skin names that
--- were equipped between d3c7fa7 and 312780c (master branch).
--- During this period, `.`-delimited skin names were internally registered with
--- `_` delimiters. This function tries to find a matching skin.
--- @param player_name (string)
--- @param skin_name (string) e.g. `player_foo_mc_bar`
--- @param be_noisy (boolean) whether to print a warning in case of mismatches`
--- @return On match, the new skin (skins.skin_class) or `nil` if nothing matched.
function skins.__fuzzy_match_skin_name(player_name, skin_name, be_noisy)
if select(2, skin_name:gsub("%.", "")) > 0 then
-- Not affected by ambiguity
return
end

for _, skin in pairs(skins.meta) do
if skin._legacy_name == skin_name then
dbgprint("Match", skin_name, skin:get_key())
return skin
local skin_obj = skins.get(name) or skins.new(name)
if is_preview then
skin_obj:set_preview(fn)
else
skin_obj:set_texture(fn)
skin_obj:set_meta("_sort_id", sort_id)
if playername then
skin_obj:set_meta("assignment", "player:"..playername)
skin_obj:set_meta("playername", playername)
end
local file = io.open(skins.modpath.."/textures/"..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(skins.modpath.."/meta/"..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
--dbgprint("Try match", skin_name, skin:get_key(), skin._legacy_name)
end

if be_noisy then
minetest.log("warning", "skinsdb: cannot find matching skin '" ..
skin_name .. "' for player '" .. player_name .. "'.")
end
end

do
-- Load skins from the current mod directory
local skins_path = skins.modpath.."/textures"
local skins_dir_list = minetest.get_dir_list(skins_path)

for _, fn in pairs(skins_dir_list) do
skins.register_skin(skins_path, fn)
end
end

Expand Down
20 changes: 6 additions & 14 deletions mods/player/skinsdb/skins_updater.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ end
local root_url = "http://skinsdb.terraqueststudios.net"
local page_url = root_url .. "/api/v1/content?client=mod&page=%i" -- [1] = Page#

local download_path = skins.modpath
local meta_path = download_path .. "/meta/"
local skins_path = download_path .. "/textures/"
local mod_path = skins.modpath
local meta_path = mod_path .. "/meta/"
local skins_path = mod_path .. "/textures/"

-- Fancy debug wrapper to download an URL
local function fetch_url(url, callback)
Expand Down Expand Up @@ -80,22 +80,14 @@ local function unsafe_file_write(path, contents)
end

-- Takes a valid skin table from the Skins Database and saves it
local function save_single_skin(skin)
local function safe_single_skin(skin)
local meta = {
skin.name,
skin.author,
skin.license
}

local name = "character." .. skin.id
do
local legacy_name = "character_" .. skin.id
local fh = ie.io.open(skins_path .. legacy_name .. ".png", "r")
-- Use the old name if either the texture ...
if fh then
name = legacy_name
end
end
local name = "character" .. skins.fsep .. skin.id

-- core.safe_file_write does not work here
unsafe_file_write(
Expand Down Expand Up @@ -136,7 +128,7 @@ internal.fetch_function = function(pages_total, start_page, len)
assert(skin.id ~= "")

if skin.id ~= 1 then -- Skin 1 is bundled with skinsdb
save_single_skin(skin)
safe_single_skin(skin)
end
end

Expand Down
45 changes: 19 additions & 26 deletions mods/player/skinsdb/textures/readme.txt
Original file line number Diff line number Diff line change
@@ -1,32 +1,25 @@
This location is where you can put your custom skins.
In this folder the skin files could be placed according the following file naming convention.

skinsdb uses an underscore as default seperator for filename splitting which can cause problems with playernames containing "_",
see https://github.com/minetest-mods/skinsdb/issues/54.
The config setting skinsdb_fsep (texture filename seperator) was added as a workaround which also offers "."(dot) as seperator,
dot is the only character which is allowed in textures but not in playernames.
To keep compatibility with older versions underscore is the default value.

List of accepted texture names
------------------------------
fresh install:
you should change the seperator to "." to avoid that problem.
existing install:
- change the filenames according to the naming convention with dot as seperator instead of underscore
- change the texture filename seperator in settings or add "skinsdb_fsep = ." to your minetest.conf before starting your server

Public skin available for all users:
character.[number or name].png
character_[number-or-name].png

One or multiple private skins for player "[nick]":
player.[nick].png
player.[nick].[number or name].png
One or multiple private skins for player "nick":
player_[nick].png or
player_[nick]_[number-or-name].png

Skin previews for public and private skins:
character.[number or name].preview.png
player.[nick].preview.png
player.[nick].[number or name].preview.png

Note: This is optional and overrides automatically generated preciewws.


Legacy texture names
--------------------

The character `_` is accepted in player names, thus it is not recommended to
use such file names. For compatibility reasons, they are still recognized.

character_[number or name].png
player_[nick].png
player_[nick]_[number or name].png

... and corresponding previews that end in `_preview.png`.
Preview files for public and private skins.
Optional, overrides the generated preview
character_*_preview.png or
player_*_*_preview.png
Loading

0 comments on commit 9743d72

Please sign in to comment.