Add simple skins skins support

This commit is contained in:
Johannes Fritz 2022-09-06 12:51:43 -05:00
parent 8e6b6393c2
commit 413c6292ff
11 changed files with 292 additions and 111 deletions

@ -231,31 +231,22 @@ filled_wield_def._mcl_wieldview_item = "mcl_maps:filled_map"
local mcl_skins_enabled = minetest.global_exists("mcl_skins") local mcl_skins_enabled = minetest.global_exists("mcl_skins")
local function player_base_to_node_id(base, colorspec, sex)
return base:gsub("%.", "") .. minetest.colorspec_to_colorstring(colorspec):gsub("#", "") .. sex
end
if mcl_skins_enabled then if mcl_skins_enabled then
local bases = mcl_skins.base
local base_colors = mcl_skins.base_color
-- Generate a node for every skin -- Generate a node for every skin
for _, base in pairs(bases) do local list = mcl_skins.get_skin_list()
for _, base_color in pairs(base_colors) do for _, skin in pairs(list) do
local node_id = player_base_to_node_id(base, base_color, "male") if skin.slim_arms then
local texture = mcl_skins.make_hand_texture(base, base_color)
local male = table.copy(filled_wield_def)
male._mcl_hand_id = node_id
male.mesh = "mcl_meshhand.b3d"
male.tiles = {texture}
minetest.register_node("mcl_maps:filled_map_" .. node_id, male)
node_id = player_base_to_node_id(base, base_color, "female")
local female = table.copy(filled_wield_def) local female = table.copy(filled_wield_def)
female._mcl_hand_id = node_id female._mcl_hand_id = skin.id
female.mesh = "mcl_meshhand_female.b3d" female.mesh = "mcl_meshhand_female.b3d"
female.tiles = {texture} female.tiles = {skin.texture}
minetest.register_node("mcl_maps:filled_map_" .. node_id, female) minetest.register_node("mcl_maps:filled_map_" .. skin.id, female)
else
local male = table.copy(filled_wield_def)
male._mcl_hand_id = skin.id
male.mesh = "mcl_meshhand.b3d"
male.tiles = {skin.texture}
minetest.register_node("mcl_maps:filled_map_" .. skin.id, male)
end end
end end
else else

@ -21,31 +21,22 @@ local node_def = {
range = minetest.registered_items[""].range range = minetest.registered_items[""].range
} }
local function player_base_to_node_id(base, colorspec, sex)
return base:gsub("%.", "") .. minetest.colorspec_to_colorstring(colorspec):gsub("#", "") .. sex
end
if mcl_skins_enabled then if mcl_skins_enabled then
local bases = mcl_skins.base
local base_colors = mcl_skins.base_color
-- Generate a node for every skin -- Generate a node for every skin
for _, base in pairs(bases) do local list = mcl_skins.get_skin_list()
for _, base_color in pairs(base_colors) do for _, skin in pairs(list) do
local node_id = player_base_to_node_id(base, base_color, "male") if skin.slim_arms then
local texture = mcl_skins.make_hand_texture(base, base_color)
local male = table.copy(node_def)
male._mcl_hand_id = node_id
male.mesh = "mcl_meshhand.b3d"
male.tiles = {texture}
minetest.register_node("mcl_meshhand:" .. node_id, male)
node_id = player_base_to_node_id(base, base_color, "female")
local female = table.copy(node_def) local female = table.copy(node_def)
female._mcl_hand_id = node_id female._mcl_hand_id = skin.id
female.mesh = "mcl_meshhand_female.b3d" female.mesh = "mcl_meshhand_female.b3d"
female.tiles = {texture} female.tiles = {skin.texture}
minetest.register_node("mcl_meshhand:" .. node_id, female) minetest.register_node("mcl_meshhand:" .. skin.id, female)
else
local male = table.copy(node_def)
male._mcl_hand_id = skin.id
male.mesh = "mcl_meshhand.b3d"
male.tiles = {skin.texture}
minetest.register_node("mcl_meshhand:" .. skin.id, male)
end end
end end
else else
@ -58,8 +49,7 @@ end
if mcl_skins_enabled then if mcl_skins_enabled then
-- Change the player's hand to their skin -- Change the player's hand to their skin
mcl_skins.register_on_set_skin(function(player) mcl_skins.register_on_set_skin(function(player)
local data = mcl_skins.players[player:get_player_name()] local node_id = mcl_skins.get_node_id_by_player(player)
local node_id = player_base_to_node_id(data.base, data.base_color, data.slim_arms and "female" or "male")
player:get_inventory():set_stack("hand", 1, "mcl_meshhand:" .. node_id) player:get_inventory():set_stack("hand", 1, "mcl_meshhand:" .. node_id)
end) end)
else else

@ -1,6 +1,7 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2022 MrRar Copyright (c) 2022 MrRar
Copyright (c) 2016 TenPlus1
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

@ -1,11 +1,11 @@
# mcl_skins # Mineclone Skins
This mod allows advanced skin customization. This mod allows advanced skin customization.
Use the /skin command to open the skin configuration screen. Use the /skin command to open the skin configuration screen.
## License ## License
Code under MIT license Code under MIT license
Author: MrRar Author: TenPlus1, Zeg9, MrRar
See image_credits.txt for image licensing. See image_credits.txt for image licensing.
@ -48,9 +48,18 @@ This parameter is optional. Must be a number. If it is not a valid page number t
Register a function to be called whenever a player skin changes. Register a function to be called whenever a player skin changes.
The function will be given a player ObjectRef as a parameter. The function will be given a player ObjectRef as a parameter.
### `mcl_skins.make_hand_texture(base, colorspec)` ### `mcl_skins.get_skin_list()`
Generate a texture string from a base texture and color. This function is used by mods that want a list of skins to register nodes that use the player skin as a texture.
This function is used by mods that want to have a first person hand textured like the player skin. Returns an array of tables containing information about each skin.
Each table contains the following properties:
`id`: A string representing the node ID. A node can be registered using this node ID.
`texture`: A texture string that can be used in the node defintion.
`slim_arms`: A boolean value. If true, this texture is used with the "female" player mesh. Otherwise the regular mesh is to be used.
### `mcl_skins.get_node_id_by_player(player)`
`player` is a player ObjectRef.
Returns a string node ID based on players current skin for use by mods that want to register nodes that use the player skin.
### `mcl_skins.save(player)` ### `mcl_skins.save(player)`
Save player skin. `player` is a player ObjectRef. Save player skin. `player` is a player ObjectRef.
@ -67,7 +76,7 @@ These colors are separate from `mcl_skins.color` because some mods register two
A table of ColorSpec integers that the player can select to color colorable skin items. A table of ColorSpec integers that the player can select to color colorable skin items.
### `mcl_skins.players` ### `mcl_skins.players`
A table mapped by player name containing tables holding the player's selected skin items and colors. A table mapped by player ObjectRef containing tables holding the player's selected skin items and colors.
Only stores skin information for logged in users. Only stores skin information for logged in users.
### mcl_skins.compile_skin(skin) ### mcl_skins.compile_skin(skin)

@ -2,6 +2,7 @@ local S = minetest.get_translator("mcl_skins")
local color_to_string = minetest.colorspec_to_colorstring local color_to_string = minetest.colorspec_to_colorstring
mcl_skins = { mcl_skins = {
simple_skins = {},
item_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"}, item_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"},
tab_names = {"template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"}, tab_names = {"template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"},
tab_descriptions = { tab_descriptions = {
@ -14,7 +15,8 @@ mcl_skins = {
bottom = S("Bottoms"), bottom = S("Bottoms"),
top = S("Tops"), top = S("Tops"),
hair = S("Hairs"), hair = S("Hairs"),
headwear = S("Headwears") headwear = S("Headwears"),
skin = S("Skins"),
}, },
steve = {}, -- Stores skin values for Steve skin steve = {}, -- Stores skin values for Steve skin
alex = {}, -- Stores skin values for Alex skin alex = {}, -- Stores skin values for Alex skin
@ -70,10 +72,13 @@ function mcl_skins.register_item(item)
end end
function mcl_skins.save(player) function mcl_skins.save(player)
local name = player:get_player_name() local skin = mcl_skins.players[player]
local skin = mcl_skins.players[name]
if not skin then return end if not skin then return end
player:get_meta():set_string("mcl_skins:skin", minetest.serialize(skin))
local meta = player:get_meta()
meta:set_string("mcl_skins:skin", minetest.serialize(skin))
meta:set_string("mcl_skins:skin_id", tostring(skin.simple_skins_id or ""))
end end
minetest.register_chatcommand("skin", { minetest.register_chatcommand("skin", {
@ -82,26 +87,19 @@ minetest.register_chatcommand("skin", {
func = function(name, param) mcl_skins.show_formspec(minetest.get_player_by_name(name)) end func = function(name, param) mcl_skins.show_formspec(minetest.get_player_by_name(name)) end
}) })
function mcl_skins.make_hand_texture(base, colorspec) function mcl_skins.compile_skin(skin)
local output = "" if skin.simple_skins_id then
if mcl_skins.masks[base] then return mcl_skins.simple_skins[skin.simple_skins_id].texture
output = mcl_skins.masks[base] ..
"^[colorize:" .. color_to_string(colorspec) .. ":alpha"
end
if #output > 0 then output = output .. "^" end
output = output .. base
return output
end end
function mcl_skins.compile_skin(skin)
local output = "" local output = ""
for i, tab in pairs(mcl_skins.item_names) do for i, item in pairs(mcl_skins.item_names) do
local texture = skin[tab] local texture = skin[item]
if texture and texture ~= "blank.png" then if texture and texture ~= "blank.png" then
if skin[tab .. "_color"] and mcl_skins.masks[texture] then if skin[item .. "_color"] and mcl_skins.masks[texture] then
if #output > 0 then output = output .. "^" end if #output > 0 then output = output .. "^" end
local color = color_to_string(skin[tab .. "_color"]) local color = color_to_string(skin[item .. "_color"])
output = output .. output = output ..
"(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)" "(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)"
end end
@ -117,11 +115,17 @@ function mcl_skins.update_player_skin(player)
return return
end end
local skin = mcl_skins.players[player:get_player_name()] local skin = mcl_skins.players[player]
mcl_player.player_set_skin(player, mcl_skins.compile_skin(skin)) mcl_player.player_set_skin(player, mcl_skins.compile_skin(skin))
local model = skin.slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d" local slim_arms
if skin.simple_skins_id then
slim_arms = mcl_skins.simple_skins[skin.simple_skins_id].slim_arms
else
slim_arms = skin.slim_arms
end
local model = slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d"
mcl_player.player_set_model(player, model) mcl_player.player_set_model(player, model)
mcl_inventory.update_inventory_formspec(player) mcl_inventory.update_inventory_formspec(player)
@ -136,30 +140,34 @@ minetest.register_on_joinplayer(function(player)
local function table_get_random(t) local function table_get_random(t)
return t[math.random(#t)] return t[math.random(#t)]
end end
local name = player:get_player_name()
local skin = player:get_meta():get_string("mcl_skins:skin") local skin = player:get_meta():get_string("mcl_skins:skin")
if skin then if skin then
skin = minetest.deserialize(skin) skin = minetest.deserialize(skin)
end end
if skin then if skin then
mcl_skins.players[name] = skin mcl_skins.players[player] = skin
else else
if math.random() > 0.5 then if math.random() > 0.5 then
skin = table.copy(mcl_skins.steve) skin = table.copy(mcl_skins.steve)
else else
skin = table.copy(mcl_skins.alex) skin = table.copy(mcl_skins.alex)
end end
mcl_skins.players[name] = skin mcl_skins.players[player] = skin
end
mcl_skins.players[player].simple_skins_id = nil
if #mcl_skins.simple_skins > 0 then
local skin_id = tonumber(player:get_meta():get_string("mcl_skins:skin_id"))
if skin_id and mcl_skins.simple_skins[skin_id] then
mcl_skins.players[player].simple_skins_id = skin_id
end
end end
mcl_skins.save(player) mcl_skins.save(player)
mcl_skins.update_player_skin(player) mcl_skins.update_player_skin(player)
end) end)
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name() mcl_skins.players[player] = nil
if name then
mcl_skins.players[name] = nil
end
end) end)
mcl_skins.registered_on_set_skins = {} mcl_skins.registered_on_set_skins = {}
@ -169,7 +177,9 @@ function mcl_skins.register_on_set_skin(func)
end end
function mcl_skins.show_formspec(player, active_tab, page_num) function mcl_skins.show_formspec(player, active_tab, page_num)
active_tab = active_tab or "template" local skin = mcl_skins.players[player]
local default = #mcl_skins.simple_skins > 0 and "skin" or "template"
active_tab = active_tab or default
page_num = page_num or 1 page_num = page_num or 1
local page_count local page_count
@ -179,13 +189,16 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
if page_num > page_count then if page_num > page_count then
page_num = page_count page_num = page_count
end end
elseif active_tab == "skin" then
page_count = math.ceil((#mcl_skins.simple_skins + 2) / 8)
if page_num > page_count then
page_num = page_count
end
else else
page_num = 1 page_num = 1
page_count = 1 page_count = 1
end end
local player_name = player:get_player_name()
local skin = mcl_skins.players[player_name]
local formspec = "formspec_version[3]size[13.2,11]" local formspec = "formspec_version[3]size[13.2,11]"
for i, tab in pairs(mcl_skins.tab_names) do for i, tab in pairs(mcl_skins.tab_names) do
@ -197,17 +210,66 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
local y = 0.3 + (i - 1) * 0.8 local y = 0.3 + (i - 1) * 0.8
formspec = formspec .. formspec = formspec ..
"button[0.3," .. y .. ";3,0.8;" .. tab .. ";" .. mcl_skins.tab_descriptions[tab] .. "]" "button[0.3," .. y .. ";3,0.8;" .. tab .. ";" .. mcl_skins.tab_descriptions[tab] .. "]"
if skin.simple_skins_id then break end
end end
local mesh = skin.slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d" local slim_arms
if skin.simple_skins_id then
slim_arms = mcl_skins.simple_skins[skin.simple_skins_id].slim_arms
else
slim_arms = skin.slim_arms
end
local mesh = slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d"
formspec = formspec .. formspec = formspec ..
"model[10,0.3;3,7;player_mesh;" .. mesh .. ";" .. "model[10,0.3;3,7;player_mesh;" .. mesh .. ";" ..
mcl_skins.compile_skin(skin) .. mcl_skins.compile_skin(skin) ..
",blank.png,blank.png;0,180;false;true;0,0;0]" ",blank.png,blank.png;0,180;false;true;0,0;0]"
if active_tab == "skin" then
local page_start = (page_num - 1) * 8 - 1
local page_end = math.min(page_start + 8 - 1, #mcl_skins.simple_skins)
formspec = formspec ..
"style_type[button;bgcolor=#00000000]"
if active_tab == "template" then local skin = table.copy(skin)
skin_id = skin.simple_skins_id or -1
skin.simple_skins_id = nil
local skins = table.copy(mcl_skins.simple_skins)
skins[-1] = {
slim_arms = skin.slim_arms,
texture = mcl_skins.compile_skin(skin),
}
for i = page_start, page_end do
local skin = skins[i]
local j = i - page_start - 1
local mesh = skin.slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d"
local x = 3.5 + (j + 1) % 4 * 1.6
local y = 0.3 + math.floor((j + 1) / 4) * 3.1
formspec = formspec ..
"model[" .. x .. "," .. y .. ";1.5,3;player_mesh;" .. mesh .. ";" ..
skin.texture ..
",blank.png,blank.png;0,180;false;true;0,0;0]"
if skin_id == i then
formspec = formspec ..
"style[" .. i ..
";bgcolor=;bgimg=mcl_skins_select_overlay.png;" ..
"bgimg_pressed=mcl_skins_select_overlay.png;bgimg_middle=14,14]"
end
formspec = formspec ..
"button[" .. x .. "," .. y .. ";1.5,3;" .. i .. ";]"
end
if page_start == -1 then
formspec = formspec .. "image[3.85,1;0.8,0.8;mcl_skins_button.png]"
end
elseif active_tab == "template" then
formspec = formspec .. formspec = formspec ..
"model[4,2;2,3;player_mesh;mcl_armor_character.b3d;" .. "model[4,2;2,3;player_mesh;mcl_armor_character.b3d;" ..
mcl_skins.compile_skin(mcl_skins.steve) .. mcl_skins.compile_skin(mcl_skins.steve) ..
@ -223,7 +285,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
elseif mcl_skins[active_tab] then elseif mcl_skins[active_tab] then
formspec = formspec .. formspec = formspec ..
"style_type[button;border=false;bgcolor=#00000000]" "style_type[button;bgcolor=#00000000]"
local textures = mcl_skins[active_tab] local textures = mcl_skins[active_tab]
local page_start = (page_num - 1) * 16 + 1 local page_start = (page_num - 1) * 16 + 1
local page_end = math.min(page_start + 16 - 1, #textures) local page_end = math.min(page_start + 16 - 1, #textures)
@ -264,19 +326,19 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
if skin[active_tab] == texture then if skin[active_tab] == texture then
formspec = formspec .. formspec = formspec ..
"style[" .. texture .. ";border=false;bgcolor=#00000000]" .. "style[" .. texture ..
"image_button[" .. x .. "," .. y .. ";bgcolor=;bgimg=mcl_skins_select_overlay.png;" ..
";1.5,1.5;mcl_skins_select_overlay.png;" .. texture .. ";]" "bgimg_pressed=mcl_skins_select_overlay.png;bgimg_middle=14,14]"
else end
formspec = formspec .. "button[" .. x .. "," .. y .. ";1.5,1.5;" .. texture .. ";]" formspec = formspec .. "button[" .. x .. "," .. y .. ";1.5,1.5;" .. texture .. ";]"
end end
end
elseif active_tab == "arm" then elseif active_tab == "arm" then
local thick_overlay = not skin.slim_arms and "^mcl_skins_select_overlay.png" or "" local x = skin.slim_arms and 4.7 or 3.6
local slim_overlay = skin.slim_arms and "^mcl_skins_select_overlay.png" or ""
formspec = formspec .. formspec = formspec ..
"image_button[3.6,0.3;1,1;mcl_skins_thick_arms.png" .. thick_overlay ..";thick_arms;]" .. "image_button[3.6,0.3;1,1;mcl_skins_thick_arms.png;thick_arms;]" ..
"image_button[4.7,0.3;1,1;mcl_skins_slim_arms.png" .. slim_overlay ..";slim_arms;]" "image_button[4.7,0.3;1,1;mcl_skins_slim_arms.png;slim_arms;]" ..
"style[arm;bgcolor=;bgimg=mcl_skins_select_overlay.png;bgimg_middle=14,14;bgimg_pressed=mcl_skins_select_overlay.png]" ..
"button[" .. x .. ",0.3;1,1;arm;]"
end end
@ -287,11 +349,6 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
local tab_color = active_tab .. "_color" local tab_color = active_tab .. "_color"
local selected_color = skin[tab_color] local selected_color = skin[tab_color]
for i, colorspec in pairs(colors) do for i, colorspec in pairs(colors) do
local overlay = ""
if selected_color == colorspec then
overlay = "^mcl_skins_select_overlay.png"
end
local color = color_to_string(colorspec) local color = color_to_string(colorspec)
i = i - 1 i = i - 1
local x = 3.6 + i % 6 * 0.9 local x = 3.6 + i % 6 * 0.9
@ -299,7 +356,15 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
formspec = formspec .. formspec = formspec ..
"image_button[" .. x .. "," .. y .. "image_button[" .. x .. "," .. y ..
";0.8,0.8;blank.png^[noalpha^[colorize:" .. ";0.8,0.8;blank.png^[noalpha^[colorize:" ..
color .. ":alpha" .. overlay .. ";" .. colorspec .. ";]" color .. ":alpha;" .. colorspec .. ";]"
if selected_color == colorspec then
formspec = formspec ..
"style[" .. color ..
";bgcolor=;bgimg=mcl_skins_select_overlay.png;bgimg_middle=14,14;bgimg_pressed=mcl_skins_select_overlay.png]" ..
"button[" .. x .. "," .. y .. ";0.8,0.8;" .. color .. ";]"
end
end end
if not (active_tab == "base") then if not (active_tab == "base") then
@ -345,6 +410,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
"label[6.3,7.2;" .. page_num .. " / " .. page_count .. "]" "label[6.3,7.2;" .. page_num .. " / " .. page_count .. "]"
end end
local player_name = player:get_player_name()
minetest.show_formspec(player_name, "mcl_skins:" .. active_tab .. "_" .. page_num, formspec) minetest.show_formspec(player_name, "mcl_skins:" .. active_tab .. "_" .. page_num, formspec)
end end
@ -367,11 +433,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if not page_num or not active_tab then return true end if not page_num or not active_tab then return true end
page_num = math.floor(tonumber(page_num) or 1) page_num = math.floor(tonumber(page_num) or 1)
local player_name = player:get_player_name()
-- Cancel formspec resend after scrollbar move -- Cancel formspec resend after scrollbar move
if mcl_skins.players[player_name].form_send_job then if mcl_skins.players[player].form_send_job then
mcl_skins.players[player_name].form_send_job:cancel() mcl_skins.players[player].form_send_job:cancel()
end end
if fields.quit then if fields.quit then
@ -380,12 +444,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
if fields.alex then if fields.alex then
mcl_skins.players[player_name] = table.copy(mcl_skins.alex) mcl_skins.players[player] = table.copy(mcl_skins.alex)
mcl_skins.update_player_skin(player) mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num) mcl_skins.show_formspec(player, active_tab, page_num)
return true return true
elseif fields.steve then elseif fields.steve then
mcl_skins.players[player_name] = table.copy(mcl_skins.steve) mcl_skins.players[player] = table.copy(mcl_skins.steve)
mcl_skins.update_player_skin(player) mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num) mcl_skins.show_formspec(player, active_tab, page_num)
return true return true
@ -398,7 +462,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
end end
local skin = mcl_skins.players[player_name] local skin = mcl_skins.players[player]
if not skin then return true end if not skin then return true end
if fields.next_page then if fields.next_page then
@ -439,12 +503,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local color = 0xff000000 + red * 0x10000 + green * 0x100 + blue local color = 0xff000000 + red * 0x10000 + green * 0x100 + blue
if color >= 0 and color <= 0xffffffff then if color >= 0 and color <= 0xffffffff then
-- We delay resedning the form because otherwise it will break dragging scrollbars -- We delay resedning the form because otherwise it will break dragging scrollbars
mcl_skins.players[player_name].form_send_job = minetest.after(0.2, function() mcl_skins.players[player].form_send_job = minetest.after(0.2, function()
if player and player:is_player() then if player and player:is_player() then
skin[active_tab .. "_color"] = color skin[active_tab .. "_color"] = color
mcl_skins.update_player_skin(player) mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num) mcl_skins.show_formspec(player, active_tab, page_num)
mcl_skins.players[player_name].form_send_job = nil mcl_skins.players[player].form_send_job = nil
end end
end) end)
return true return true
@ -459,6 +523,21 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
end end
if field and active_tab == "skin" then
local skin_id = tonumber(field)
skin_id = skin_id and math.floor(skin_id) or 0
if
#mcl_skins.simple_skins > 0 and
skin_id >= -1 and skin_id <= #mcl_skins.simple_skins
then
if skin_id == -1 then skin_id = nil end
skin.simple_skins_id = skin_id
mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num)
end
return true
end
-- See if field is a texture -- See if field is a texture
if field and mcl_skins[active_tab] then if field and mcl_skins[active_tab] then
for i, texture in pairs(mcl_skins[active_tab]) do for i, texture in pairs(mcl_skins[active_tab]) do

@ -1,4 +1,8 @@
local mod_path = minetest.get_modpath(minetest.get_current_modname()) local mod_path = minetest.get_modpath(minetest.get_current_modname())
local mcl_skins_enabled = minetest.settings:get_bool("mcl_enable_skin_customization", true) local mcl_skins_enabled = minetest.settings:get_bool("mcl_enable_skin_customization", true)
if mcl_skins_enabled then dofile(mod_path .. "/edit_skin.lua") end if mcl_skins_enabled then
dofile(mod_path .. "/edit_skin.lua")
dofile(mod_path .. "/simple_skins.lua")
dofile(mod_path .. "/mesh_hand.lua")
end

@ -173,7 +173,8 @@
}, },
{ {
"type": "headwear", "type": "headwear",
"steve": true "steve": true,
"alex": true
}, },
{ {
"type": "bottom", "type": "bottom",

@ -1,4 +1,5 @@
# textdomain: mcl_skins # textdomain: mcl_skins
Skins=
Templates= Templates=
Arm size= Arm size=
Bases= Bases=

@ -0,0 +1,53 @@
local function make_texture(base, colorspec)
local output = ""
if mcl_skins.masks[base] then
output = mcl_skins.masks[base] ..
"^[colorize:" .. minetest.colorspec_to_colorstring(colorspec) .. ":alpha"
end
if #output > 0 then output = output .. "^" end
output = output .. base
return output
end
function mcl_skins.get_skin_list()
local list = {}
for _, base in pairs(mcl_skins.base) do
for _, base_color in pairs(mcl_skins.base_color) do
local id = base:gsub(".png$", "") .. minetest.colorspec_to_colorstring(base_color):gsub("#", "")
local female = {
texture = make_texture(base, base_color),
slim_arms = true,
id = id .. "_female"
}
table.insert(list, female)
local male = {
texture = make_texture(base, base_color),
slim_arms = false,
id = id .. "_male"
}
table.insert(list, male)
end
end
for _, skin in pairs(mcl_skins.simple_skins) do
table.insert(list, {
texture = skin.texture,
slim_arms = skin.slim_arms,
id = skin.texture:gsub(".png$", "") .. "_" .. (skin.slim_arms and "female" or "male"),
})
end
return list
end
function mcl_skins.get_node_id_by_player(player)
local skin = mcl_skins.players[player]
if skin.simple_skins_id then
local skin = mcl_skins.simple_skins[skin.simple_skins_id]
return skin.texture:gsub(".png$", "") ..
"_" .. (skin.slim_arms and "female" or "male")
else
return skin.base:gsub(".png$", "") ..
minetest.colorspec_to_colorstring(skin.base_color):gsub("#", "") ..
"_" .. (skin.slim_arms and "female" or "male")
end
end

@ -0,0 +1,52 @@
local function init_simple_skins()
local id, f, data, skin = 0
local mod_path = minetest.get_modpath("mcl_skins")
while true do
if id == 0 then
skin = "character.png"
else
skin = "mcl_skins_character_" .. id .. ".png"
-- Does skin file exist?
f = io.open(mod_path .. "/textures/" .. skin)
-- escape loop if not found
if not f then
break
end
f:close()
end
local metafile
-- does metadata exist for that skin file ?
if id == 0 then
metafile = "mcl_skins_character.txt"
else
metafile = "mcl_skins_character_"..id..".txt"
end
f = io.open(mod_path .. "/meta/" .. metafile)
data = nil
if f then
data = minetest.deserialize("return {" .. f:read("*all") .. "}")
f:close()
end
-- add metadata to list
mcl_skins.simple_skins[id] = {
texture = skin,
slim_arms = data and data.gender == "female",
}
id = id + 1
end
if #mcl_skins.simple_skins > 0 then
table.insert(mcl_skins.tab_names, 1, "skin")
else
mcl_skins.simple_skins = {}
end
end
init_simple_skins()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 B

After

Width:  |  Height:  |  Size: 178 B