forked from ThomasMonroe314/ugxrealms
185 lines
4.6 KiB
Lua
185 lines
4.6 KiB
Lua
wardrobe = wardrobe or {};
|
|
wardrobe.storage = wardrobe.storage or {};
|
|
|
|
|
|
local MOD_NAME = minetest.get_current_modname();
|
|
local MOD_PATH = minetest.get_modpath(MOD_NAME);
|
|
local WORLD_PATH = minetest.get_worldpath();
|
|
|
|
local SKIN_FILES = { MOD_PATH.."/skins.txt", WORLD_PATH.."/skins.txt" };
|
|
local PLAYER_SKIN_DB = WORLD_PATH.."/playerSkins.txt";
|
|
|
|
|
|
local function removePrefix(str, prefix)
|
|
local n = #prefix;
|
|
if #str >= n and string.sub(str, 1, n) == prefix then
|
|
return string.sub(str, n+1);
|
|
else
|
|
return str;
|
|
end
|
|
end
|
|
|
|
local function removeSuffix(str, suffix)
|
|
local n = #suffix;
|
|
if #str >= n and string.sub(str, -n, -1) == suffix then
|
|
return string.sub(str, 1, -(n+1));
|
|
else
|
|
return str;
|
|
end
|
|
end
|
|
|
|
local function trimTail(str)
|
|
local e = string.find(str, "%s+$");
|
|
return (e and string.sub(str, e-1)) or str;
|
|
end
|
|
|
|
local function parsePlayerSkinLine(line)
|
|
local k, v;
|
|
local p = string.find(line, "%S");
|
|
if p and not string.find(line, "^%-%-", p) then
|
|
local ss, se = string.find(line, "%s*:%s*", p);
|
|
if ss then
|
|
k = string.sub(line, p, ss-1);
|
|
v = trimTail(string.sub(line, se+1));
|
|
if k == "" then k = nil; end
|
|
if v == "" then v = nil; end
|
|
end
|
|
end
|
|
return k, v;
|
|
end
|
|
|
|
local function parseSkinLine(line)
|
|
local k, v, n, e;
|
|
|
|
local p = string.find(line, "%S");
|
|
if p then
|
|
n, e = string.find(line, "^%-%-?", p);
|
|
if not n or n == e then
|
|
if n then p = n+1; end
|
|
local ss, se = string.find(line, "%s*:%s*", p);
|
|
if ss then
|
|
k = string.sub(line, p, ss-1);
|
|
v = trimTail(string.sub(line, se+1));
|
|
if v == "" then v = nil; end
|
|
else
|
|
k = trimTail(string.sub(line, p));
|
|
end
|
|
if k == "" then k = nil; end
|
|
end
|
|
end
|
|
|
|
return k, v, n;
|
|
end
|
|
|
|
--- Parses the files with the given paths for key/value pairs. Once a key is
|
|
-- negated, it stays negated. Otherwise, the last (non-nil) value assigned to
|
|
-- a key wins.
|
|
--
|
|
-- @return A list of non-negated keys. This may include keys for which the
|
|
-- values are nil.
|
|
-- @return A map from key to value for all non-negated keys with non-nil
|
|
-- values.
|
|
--
|
|
local function loadSkinsFromFiles(filePaths)
|
|
local normKeys, negKeys, values = {}, {}, {}
|
|
|
|
for _, filePath in ipairs(filePaths) do
|
|
local file = io.open(filePath, "r");
|
|
if file then
|
|
for line in file:lines() do
|
|
local k, v, n = parseSkinLine(line)
|
|
if k then
|
|
if n then
|
|
normKeys[k] = nil;
|
|
values[k] = nil;
|
|
negKeys[k] = k;
|
|
elseif not negKeys[k] then
|
|
normKeys[k] = k;
|
|
if v then
|
|
values[k] = v;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
file:close()
|
|
end
|
|
end
|
|
|
|
local keyList = {};
|
|
for k in pairs(normKeys) do
|
|
table.insert(keyList, k);
|
|
end
|
|
|
|
return keyList, values;
|
|
end
|
|
|
|
--- Loads skin names from skin files, storing the result in wardrobe.skins and
|
|
-- wardrobe.skinNames.
|
|
--
|
|
function wardrobe.storage.loadSkins()
|
|
local skins, skinNames = loadSkinsFromFiles(SKIN_FILES);
|
|
|
|
for i, skin in ipairs(skins) do
|
|
local name = skinNames[skin];
|
|
|
|
if not name then
|
|
local s, e;
|
|
|
|
name = removeSuffix(
|
|
removePrefix(
|
|
removePrefix(skin, MOD_NAME.."_"),
|
|
"skin_"),
|
|
".png");
|
|
|
|
if name == "" then
|
|
name = skin;
|
|
else
|
|
name = string.gsub(name, "_", " ");
|
|
end
|
|
end
|
|
|
|
skinNames[skin] = name;
|
|
end
|
|
|
|
table.sort(skins,
|
|
function(sL, sR)
|
|
return skinNames[sL] < skinNames[sR];
|
|
end);
|
|
|
|
wardrobe.skins = skins;
|
|
wardrobe.skinNames = skinNames;
|
|
end
|
|
|
|
--- Parses the player skins database file and stores the result in
|
|
-- wardrobe.playerSkins.
|
|
--
|
|
function wardrobe.storage.loadPlayerSkins()
|
|
local playerSkins = {};
|
|
|
|
local file = io.open(PLAYER_SKIN_DB, "r");
|
|
if file then
|
|
for line in file:lines() do
|
|
local name, skin = parsePlayerSkinLine(line);
|
|
if name then
|
|
playerSkins[name] = skin;
|
|
end
|
|
end
|
|
file:close();
|
|
end
|
|
|
|
wardrobe.playerSkins = playerSkins;
|
|
end
|
|
|
|
--- Writes wardrobe.playerSkins to the player skins database file.
|
|
--
|
|
function wardrobe.storage.savePlayerSkins()
|
|
local file = io.open(PLAYER_SKIN_DB, "w");
|
|
if not file then error("Couldn't write file '"..filePath.."'"); end
|
|
|
|
for name, skin in pairs(wardrobe.playerSkins) do
|
|
file:write(name, ":", skin, "\n");
|
|
end
|
|
|
|
file:close();
|
|
end
|