Use storage instead of metadata to track the current skin

This commit is contained in:
marco_a 2024-12-11 20:49:57 +01:00
parent 5e62d665b7
commit 900ed73531
2 changed files with 66 additions and 40 deletions

View File

@ -72,7 +72,7 @@ Collectible Skins uses the mod storage to store all the skins unlocked by a cert
* `collectible_skins.get_skin(skin_name)`: returns a copy of the skin corresponding to `skin_name`, if any
* `collectible_skins.get_collection(coll_name)`: returns a copy of the specified collection, format `{coll_name = coll_data}`
* `collectible_skins.get_player_skins(p_name, <filter>)`: returns a table containing as value all the skins that `p_name` has unlocked, format `{"skin_name1", "skin_name2"}`. See `get_skins(..)` for `filter`
* `collectible_skins.get_player_skin(p_name, <permanent_only>)`: returns a copy of the skin that `p_name` has currently equipped, if online.
* `collectible_skins.get_player_skin(p_name, <permanent_only>)`: returns a copy of the skin that `p_name` has currently equipped.
* `permanent_only` is a boolean that, if present, ignores the temporary skin the player might have equipped, returning the permanent one
### 2.4 Setters

View File

@ -3,6 +3,7 @@ local storage = minetest.get_mod_storage()
local S = minetest.get_translator("collectible_skins")
local function load_player_data() end
local function apply_skin() end
local function try_to_load_player() end
local function filter_checks_passed() end
local function migrate_old_skins() end
@ -18,6 +19,29 @@ local skins_to_migrate = collectible_skins.SETTINGS.migrate_skins
-- v ---- TO REMOVE IN 3.0 ---- v --
local function migrate_meta_to_storage()
local storage_keys = storage:get_keys()
if not next(storage_keys) then return end
for _, v in ipairs(storage_keys) do
if v:find("_current") then
return
end
end
-- le chiavi son per forza i nomi dell'utenza già connessasi con collectible_skins abilitata
for _, key in ipairs(storage_keys) do
storage:set_string(key .. "_current", default_skins[math.random(#default_skins)])
end
end
migrate_meta_to_storage()
-- ^ ---- TO REMOVE IN 3.0 ---- ^ --
local function register_hand_from_texture(name, texture)
local hand_name = "collectible_skins:hand_" .. name
local hand_def = {}
@ -386,7 +410,7 @@ function collectible_skins.get_player_skin(p_name, permanent_only)
if not permanent_only then
return table.copy(loaded_skins[equipped_skin[p_name]])
else
local sk_name = minetest.get_player_by_name(p_name):get_meta():get_string("collectible_skins:skin")
local sk_name = storage:get_string(p_name .. "_current") -- TODO: prob meglio avere una tabella locale al posto di accedere ogni volta alla base dati
if loaded_skins[sk_name] then
return table.copy(loaded_skins[sk_name])
@ -402,35 +426,25 @@ end
-----------------SETTERS----------------------
----------------------------------------------
-- at_login è un parametro interno che serve solo per evitare di lanciare il richiamo
-- on_set_skin anche quando si connettono
function collectible_skins.set_skin(player, skin_name, is_permanent, at_login)
function collectible_skins.set_skin(player, skin_name, is_permanent)
local p_name = player:get_player_name()
if not minetest.get_player_by_name(p_name) then return end
-- se la skin non è più in memoria, assegnane una casuale tra quelle predefinite
apply_skin(player, skin_name)
-- se l'aspetto non è più in memoria, la nuova assegnata deve essere permanente
if not loaded_skins[skin_name] then
collectible_skins.print_warning("Attempt to equipping unknown skin " .. skin_name .. " to " .. p_name .. ". Equipping a default skin instead")
skin_name = default_skins[math.random(#default_skins)]
is_permanent = true
end
player_api.set_texture(player, 1, loaded_skins[skin_name].texture)
equipped_skin[p_name] = skin_name
player:get_inventory():set_size("hand", 1)
player:get_inventory():set_stack("hand", 1, "collectible_skins:hand_" .. tostring(skin_name))
if is_permanent then
player:get_meta():set_string("collectible_skins:skin", skin_name)
end
if at_login then return end
-- eventuali richiami
for _, callback in ipairs(collectible_skins.registered_on_set_skin) do
callback(player:get_player_name(), skin_name, at_login)
callback(player:get_player_name(), skin_name)
end
if is_permanent then
storage:set_string(p_name .. "_current", skin_name)
end
end
@ -444,27 +458,18 @@ end
function load_player_data(player)
local p_name = player:get_player_name()
local p_meta = player:get_meta()
if p_meta:contains("collectible_skins:skin_ID") then
migrate_old_skins()
end
-- se lə giocante entra per la prima volta o ha perso il metadato, lo inizializzo...
-- il controllo del metadato è l'unico modo che ho trovato di sapere se qualcuno ha usato
-- minetest.remove_player sullə giocante.
if storage:get_string(p_name) == "" or not player:get_meta():contains("collectible_skins:skin") then
-- core.remove_player sullə giocante.
if storage:get_string(p_name) == "" then
players_skins[p_name] = {}
-- migrazione vecchio sistema basato sugli id
if player:get_meta():contains("collectible_skins:skin_ID") then
local p_skins = minetest.deserialize(storage:get_string(p_name))
-- se p_skins non esiste significa che hanno cancellato il mod storage, ma non i metadati degli utenti
if p_skins then
migrate_old_skins(player, p_name)
return
end
player:get_meta():set_string("collectible_skins:skin_ID", "")
end
-- sblocco gli aspetti base
for _, sk_name in pairs(default_skins) do
players_skins[p_name][sk_name] = true
@ -474,11 +479,13 @@ function load_player_data(player)
-- ...e ne assegno uno casuale
local random_ID = math.random(#default_skins)
collectible_skins.set_skin(player, default_skins[random_ID], true, true)
apply_skin(player, default_skins[random_ID])
storage:set_string(p_name .. "_current", equipped_skin[p_name])
--sennò assegno l'aspetto che aveva
else
local skin_name = player:get_meta():get_string("collectible_skins:skin")
local skin_name = storage:get_string(p_name .. "_current")
-- potrebbe già esser stato caricato da try_to_load_player, risparmio un'eventuale deserializzazione
if not players_skins[p_name] then
@ -505,12 +512,30 @@ function load_player_data(player)
end
end
collectible_skins.set_skin(player, skin_name, false, true)
apply_skin(player, skin_name)
end
end
function apply_skin(player, skin_name)
local p_name = player:get_player_name()
-- se la skin non è più in memoria, assegnane una casuale tra quelle predefinite
if not loaded_skins[skin_name] then
collectible_skins.print_warning("Attempt to equipping unknown skin " .. skin_name .. " to " .. p_name .. ". Equipping a default skin instead")
skin_name = default_skins[math.random(#default_skins)]
end
player_api.set_texture(player, 1, loaded_skins[skin_name].texture)
equipped_skin[p_name] = skin_name
player:get_inventory():set_size("hand", 1)
player:get_inventory():set_stack("hand", 1, "collectible_skins:hand_" .. tostring(skin_name))
end
function try_to_load_player(p_name)
if players_skins[p_name] then return end
@ -544,6 +569,7 @@ end
-- This means that a server which used this mod in its alpha state (i.e. A.E.S.)
-- can't convert skins as it can't touch offline players' metadata - it can only
-- perform storage conversion
-- TO REMOVE IN 2.0
function migrate_old_skins(player, p_name)
assert(skins_to_migrate ~= nil, "[COLLECTIBLE_SKINS] You need to migrate your skins using the new nomenclature system instead of IDs!"
.. "Check out the DOCS to learn about the new structure and use the setting `migrate_skins` to migrate "