skins-collectible/src/api.lua

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