diff --git a/api.lua b/api.lua index b5a8211..c408810 100644 --- a/api.lua +++ b/api.lua @@ -2,14 +2,26 @@ 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:get_player_name(), meta:get_string("skinsdb:skin_key")) + storage:set_string(player_name, meta:get_string("skinsdb:skin_key")) meta:set_string("skinsdb:skin_key", "") end - local skin = storage:get_string(player:get_player_name()) - return skins.get(skin) or skins.get(skins.default) + + 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) end -- Assign skin to player diff --git a/skinlist.lua b/skinlist.lua index 9b356c4..8f1831f 100644 --- a/skinlist.lua +++ b/skinlist.lua @@ -97,6 +97,65 @@ local function process_skin_texture(path, filename) end 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 + + --[[ + Public skin names: + character_[number] + Private skin names: + player_sam_doe + player_sam_doe_1234 <-- might also belong to player "sam_doe_1233" + . ^^^^^^^^^^^^ identifier + ^^^^^^------------- prefix + + Approach: try to find a match for the longest possible name + Assumption 1: There are no skin variations without numeric ending + Assumption 2: Player names to not end with `_%d+` + ]] + + local prefix, identifier = unpack(skin_name:split("_", true, 1)) + local for_player, number + if prefix == "player" then + for_player, number = identifier:match("^([%w_]+)_(%d+)$") + if not number then + for_player = identifier + end + else -- character + number = identifier + end + + local skin = nil + if not for_player or for_player == player_name then + skin = skins.get(prefix + .. (for_player and ("." .. for_player) or "") + .. (number and ("." .. number) or "") + ) + end + + if skin then + -- MATCH! + dbgprint("Match", skin_name, skin:get_key()) + return skin + 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" diff --git a/textures/readme.txt b/textures/readme.txt index 44ab8fd..3891dc9 100644 --- a/textures/readme.txt +++ b/textures/readme.txt @@ -26,7 +26,7 @@ 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].png player_[nick]_[number or name].png ... and corresponding previews that end in `_preview.png`.