local yaml = dofile(minetest.get_modpath("skins_collectible") .. "/src/yaml_parser.lua") local storage = minetest.get_mod_storage() local players_skins = {} -- KEY: p_name; VALUE: {skins_ID} local loaded_skins = {} local equipped_skin = {} -- KEY: p_name; VALUE: skin ID local function load_skins() local dir = minetest.get_worldpath() .. "/skins" local file = minetest.get_dir_list(dir, false) local modpath = minetest.get_modpath("skins_collectible") local i18n_dir = modpath .. "/locale/skins" local txtr_dir = modpath .. "/textures/skins" -- se la cartella delle skin non esiste/è vuota, copio la cartella base `skins` -- dentro quella del mondo. Sennò copio /locale e /textures dal mondo alla mod if not next(file) then local src_dir = minetest.get_modpath("skins_collectible") .. "/skins" minetest.cpdir(src_dir, dir) minetest.cpdir(src_dir .. "/locale", i18n_dir) minetest.cpdir(src_dir .. "/textures", txtr_dir) os.remove(dir .. "/README.md") file = minetest.get_dir_list(dir) else minetest.cpdir(dir .. "/locale", i18n_dir) minetest.cpdir(dir .. "/textures", txtr_dir) end for _, f_name in pairs(file) do if f_name:sub(-4) == ".yml" or f_name:sub(-5) == ".yaml" then local file = io.open(dir .. "/" .. f_name, "r") local skins = yaml.parse(file:read("*all")) for ID, skin in pairs(skins) do -- il decodificatore aggiunge_N ai doppioni, per diversificarli e salvarli entrambi. Tolgo quindi _ecc -- da eventuali cifre iniziali per vedere se già esiste (se è stringa, è errore a prescindere) if type(ID) == "string" then assert(loaded_skins[tonumber(ID:match("(%d+)_"))] == nil, "[SKINS COLLECTIBLE] There are two or more skins with the same ID!") error("[SKINS COLLECTIBLE] Invalid skin ID '" .. ID .. "': numbers only!") end assert(skin.name, "[SKINS COLLECTIBLE] Skin #" .. ID .. " has no name!") assert(skin.description, "[SKINS COLLECTIBLE] Skin #" .. ID .. " has no description!") assert(skin.texture, "[SKINS COLLECTIBLE] Skin #" .. ID .. " has no texture!") loaded_skins[ID] = { name = skin.name, description = skin.description, hint = skin.hint or "(locked)", model = skin.model, texture = skin.texture, tier = skin.tier or 1, img = skin.splash_art or "blank.png", author = skin.author or "???", } end file:close() end end end load_skins() ---------------------------------------------- -------------------CORPO---------------------- ---------------------------------------------- function skins_collectible.load_player_data(player) local p_name = player:get_player_name() -- se il giocatore entra per la prima volta, lo inizializzo... if storage:get_string(p_name) == "" then local default_skins = minetest.deserialize(minetest.settings:get("skinsc_default_skins")) players_skins[p_name] = {} -- sblocco le skin base for _, ID in pairs(default_skins) do players_skins[p_name][ID] = true end storage:set_string(p_name, minetest.serialize(players_skins[p_name])) -- ...e gli assegno una skin randomica local random_ID = math.random(6) skins_collectible.set_skin(player, random_ID, true) --sennò gli assegno la skin che aveva else local skin_ID = player:get_meta():get_int("skins_collectible:skin_ID") players_skins[p_name] = minetest.deserialize(storage:get_string(p_name)) skins_collectible.set_skin(player, skin_ID) end end function skins_collectible.unlock_skin(p_name, skin_ID) -- se la skin non esiste, annullo if not loaded_skins[skin_ID] then local error = "[SKINS_COLLECTIBLE] There has been an attempt to give player " .. p_name .. " a skin that doesn't exist (ID = " .. skin_ID .. ")!" minetest.log("warning", error) return false, error end -- se il giocatore non si è mai connesso, annullo if storage:get_string(p_name) == "" then local error = "[SKINS COLLECTIBLE] Player " .. p_name .. " is not in the skin database (meaning the player has never connected)" minetest.log("warning", error) return false, error end -- se ce l'ha già, annullo if skins_collectible.is_skin_unlocked(p_name, skin_ID) then return end local p_skins -- se è online if minetest.get_player_by_name(p_name) then p_skins = players_skins[p_name] minetest.chat_send_player(p_name, "You've unlocked the skin " .. loaded_skins[skin_ID].name .. "!") -- se è offline else p_skins = minetest.deserialize(storage:get_string(p_name)) end p_skins[skin_ID] = true storage:set_string(p_name, minetest.serialize(p_skins)) end function skins_collectible.remove_skin(p_name, skin_ID) -- se la skin non esiste, annullo if not loaded_skins[skin_ID] then local error = "[SKINS_COLLECTIBLE] There has been an attempt to remove player " .. p_name .. " a skin that doesn't exist (ID = " .. skin_ID .. ")!" minetest.log("warning", error) return false, error end -- se il giocatore non si è mai connesso, annullo if storage:get_string(p_name) == "" then local error = "[SKINS COLLECTIBLE] Player " .. p_name .. " is not in the skin database (meaning the player has never connected)" minetest.log("warning", error) return false, error end -- se già gli manca, annullo if not skins_collectible.is_skin_unlocked(p_name, skin_ID) then return end local p_skins -- se è online if minetest.get_player_by_name(p_name) then p_skins = players_skins[p_name] minetest.chat_send_player(p_name, "Your skin " .. loaded_skins[skin_ID].name .. " has been removed...") -- se è offline else p_skins = minetest.deserialize(storage:get_string(p_name)) end -- rimuovo p_skins[skin_ID] = false storage:set_string(p_name, minetest.serialize(p_skins)) end ---------------------------------------------- --------------------UTILS--------------------- ---------------------------------------------- function skins_collectible.is_skin_unlocked(p_name, skin_ID) -- per controllare anche giocatori offline local p_skins = players_skins[p_name] or minetest.deserialize(storage:get_string(p_name)) if p_skins and p_skins[skin_ID] then return true else return false end end ---------------------------------------------- -----------------GETTERS---------------------- ---------------------------------------------- function skins_collectible.get_preview(skin_ID) return string.match(loaded_skins[skin_ID].texture, "(.*)%.png") .. "_preview.png" end function skins_collectible.get_skin(skin_ID) return loaded_skins[skin_ID] end function skins_collectible.get_player_skin(p_name) return loaded_skins[equipped_skin[p_name]] end function skins_collectible.get_player_skin_ID(p_name) return equipped_skin[p_name] end function skins_collectible.get_loaded_skins_amount() return #loaded_skins end ---------------------------------------------- -----------------SETTERS---------------------- ---------------------------------------------- function skins_collectible.set_skin(player, skin_ID, is_permanent) player_api.set_texture(player, 1, loaded_skins[skin_ID].texture) local p_name = player:get_player_name() equipped_skin[p_name] = skin_ID if is_permanent then player:get_meta():set_int("skins_collectible:skin_ID", skin_ID) end -- eventuali callback for _, callback in ipairs(skins_collectible.registered_on_set_skin) do callback(player:get_player_name(), skin_ID) end end