255 lines
7.6 KiB
Lua
Executable File
255 lines
7.6 KiB
Lua
Executable File
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
|