Skins update

This commit is contained in:
parent bd37ed178c
commit 1e63f3931a
30 changed files with 233 additions and 202 deletions

View File

@ -158,8 +158,10 @@ minetest.register_on_player_inventory_action(function(player, action, inventory,
end) end)
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
mcl_player.player_set_model(player, "mcl_armor_character.b3d")
player:get_inventory():set_size("armor", 5) player:get_inventory():set_size("armor", 5)
if not minetest.global_exists("mcl_skins") then
mcl_player.player_set_model(player, "mcl_armor_character.b3d")
end
minetest.after(1, function() minetest.after(1, function()
if player:is_player() then if player:is_player() then

View File

@ -2,4 +2,4 @@ name = mcl_meshhand
author = jordan4ibanez author = jordan4ibanez
description = Applies the player skin texture to the hand. description = Applies the player skin texture to the hand.
depends = mcl_tools, mcl_player depends = mcl_tools, mcl_player
optional_depends = mcl_skins optional_depends = mcl_skins, mcl_custom_skins

View File

@ -28,28 +28,6 @@ function mcl_player.player_register_model(name, def)
models[name] = def models[name] = def
end end
-- Default player appearance
mcl_player.player_register_model("character.b3d", {
animation_speed = 30,
textures = {"character.png", },
animations = {
-- Standard animations.
stand = {x= 0, y= 79},
lay = {x=162, y=166},
walk = {x=168, y=187},
mine = {x=189, y=198},
walk_mine = {x=200, y=219},
sit = {x= 81, y=160},
sneak_stand = {x=222, y=302},
sneak_mine = {x=346, y=366},
sneak_walk = {x=304, y=323},
sneak_walk_mine = {x=325, y=344},
run_walk = {x=440, y=460},
run_walk_mine = {x=461, y=481},
sit_mount = {x=484, y=484},
},
})
-- Player stats and animations -- Player stats and animations
local player_model = {} local player_model = {}
local player_textures = {} local player_textures = {}
@ -112,6 +90,7 @@ function mcl_player.player_set_model(player, model_name)
if player_model[name] == model_name then if player_model[name] == model_name then
return return
end end
player_model[name] = model_name
player:set_properties({ player:set_properties({
mesh = model_name, mesh = model_name,
visual = "mesh", visual = "mesh",
@ -120,13 +99,7 @@ function mcl_player.player_set_model(player, model_name)
}) })
update_player_textures(player) update_player_textures(player)
mcl_player.player_set_animation(player, "stand") mcl_player.player_set_animation(player, "stand")
else
player:set_properties({
textures = { "player.png", "player_back.png", },
visual = "upright_sprite",
})
end end
player_model[name] = model_name
end end
function mcl_player.player_set_visibility(player, visible) function mcl_player.player_set_visibility(player, visible)
@ -180,7 +153,6 @@ minetest.register_on_joinplayer(function(player)
local name = player:get_player_name() local name = player:get_player_name()
mcl_player.player_attached[name] = false mcl_player.player_attached[name] = false
player_visible[name] = true player_visible[name] = true
mcl_player.player_set_model(player, "character.b3d")
player_textures[name] = {"character.png", "blank.png", "blank.png"} player_textures[name] = {"character.png", "blank.png", "blank.png"}
--player:set_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, 30) --player:set_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, 30)
player:set_fov(86.1) -- see <https://minecraft.gamepedia.com/Options#Video_settings>>>> player:set_fov(86.1) -- see <https://minecraft.gamepedia.com/Options#Video_settings>>>>

View File

@ -15,6 +15,7 @@ See image_credits.txt for image licensing.
Register a skin item. `item` is a table with item properties listed below. Register a skin item. `item` is a table with item properties listed below.
### Item properties ### Item properties
`type` `type`
Set the item type. Valid values are: "base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear" Set the item type. Valid values are: "base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"
@ -34,15 +35,32 @@ If set to true the item will be default for female character.
`steve` `steve`
If set to true the item will be default for male character. If set to true the item will be default for male character.
`rank`
This property is used to change the application order of the skin item when applied to a player.
The default ranks for each item type are:
### `mcl_skins.show_formspec(player, active_tab, page_num)` base: 10
footwear: 20
eye: 30
mouth: 40
bottom: 50
top: 60
hair: 70
headwear: 80
Lower ranks are applied to the player first and can thus be covered by higher rank items.
### `mcl_skins.show_formspec(player)`
Show the skin configuration screen. Show the skin configuration screen.
`player` is a player ObjectRef. `player` is a player ObjectRef.
`active_tab` is the tab that will be displayed. This parameter is optional.
Can be one of: "arm", "base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"
`page_num` The page number to display of there are multiple pages of items.
This parameter is optional. Must be a number. If it is not a valid page number the closest page number will be shown.
### `mcl_skins.get_skin_list()` ### `mcl_skins.get_skin_list()`
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 a list of skins to register nodes that use the player skin as a texture.
@ -50,7 +68,9 @@ Returns an array of tables containing information about each skin.
Each table contains the following properties: Each table contains the following properties:
`id`: A string representing the node ID. A node can be registered using this node ID. `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. `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. `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)` ### `mcl_skins.get_node_id_by_player(player)`
@ -71,10 +91,19 @@ These colors are separate from `mcl_skins.color` because some mods register two
### `mcl_skins.color` ### `mcl_skins.color`
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.player_skins`
A table mapped by player ObjectRef 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)`
`skin` is a table with skin item properties. `skin` is a table with skin item properties.
Returns an image string. Returns an image string.
### `mcl_skins.register_simple_skin(skin)`
`skin` is a table with the following properties:
`texture`
The texture of the skin.
`slim_arms`
A boolean value. If set to true, the slim armed player mesh will be used with this skin.

View File

@ -3,8 +3,9 @@ local color_to_string = minetest.colorspec_to_colorstring
mcl_skins = { mcl_skins = {
simple_skins = {}, simple_skins = {},
texture_to_simple_skin = {},
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 = {"skin", "template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"},
tab_descriptions = { tab_descriptions = {
template = S("Templates"), template = S("Templates"),
arm = S("Arm size"), arm = S("Arm size"),
@ -50,7 +51,9 @@ mcl_skins = {
headwear = {}, headwear = {},
masks = {}, masks = {},
preview_rotations = {}, preview_rotations = {},
players = {} ranks = {},
player_skins = {},
player_formspecs = {},
} }
function mcl_skins.register_item(item) function mcl_skins.register_item(item)
@ -66,19 +69,28 @@ function mcl_skins.register_item(item)
table.insert(mcl_skins[item.type], texture) table.insert(mcl_skins[item.type], texture)
mcl_skins.masks[texture] = item.mask mcl_skins.masks[texture] = item.mask
if item.preview_rotation then
mcl_skins.preview_rotations[texture] = item.preview_rotation mcl_skins.preview_rotations[texture] = item.preview_rotation
mcl_skins.ranks[texture] = item.rank
end end
function mcl_skins.register_simple_skin(skin)
if skin.index then
mcl_skins.simple_skins[skin.index] = skin
else
table.insert(mcl_skins.simple_skins, skin)
end
mcl_skins.texture_to_simple_skin[skin.texture] = skin
end end
function mcl_skins.save(player) function mcl_skins.save(player)
local skin = mcl_skins.players[player] local skin = mcl_skins.player_skins[player]
if not skin then return end if not skin then return end
local meta = player:get_meta() local meta = player:get_meta()
meta:set_string("mcl_skins:skin", minetest.serialize(skin)) meta:set_string("mcl_skins:skin", minetest.serialize(skin))
meta:set_string("mcl_skins:skin_id", tostring(skin.simple_skins_id or "")) -- Clear out the old way of storing the simple skin ID
meta:set_string("mcl_skins:skin_id", "")
end end
minetest.register_chatcommand("skin", { minetest.register_chatcommand("skin", {
@ -88,24 +100,34 @@ minetest.register_chatcommand("skin", {
}) })
function mcl_skins.compile_skin(skin) function mcl_skins.compile_skin(skin)
if not skin then return "blank.png" end
if skin.simple_skins_id then if skin.simple_skins_id then
return mcl_skins.simple_skins[skin.simple_skins_id].texture return skin.simple_skins_id
end end
local output = "" local ranks = {}
for i, item in pairs(mcl_skins.item_names) do local layers = {}
for i, item in ipairs(mcl_skins.item_names) do
local texture = skin[item] local texture = skin[item]
local layer = ""
local rank = mcl_skins.ranks[texture] or i * 10
if texture and texture ~= "blank.png" then if texture and texture ~= "blank.png" then
if skin[item .. "_color"] and mcl_skins.masks[texture] then if skin[item .. "_color"] and mcl_skins.masks[texture] then
if #output > 0 then output = output .. "^" end
local color = color_to_string(skin[item .. "_color"]) local color = color_to_string(skin[item .. "_color"])
output = output .. layer = "(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)"
"(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)"
end end
if #layer > 0 then layer = layer .. "^" end
layer = layer .. texture
layers[rank] = layer
table.insert(ranks, rank)
end
end
table.sort(ranks)
local output = ""
for i, rank in ipairs(ranks) do
if #output > 0 then output = output .. "^" end if #output > 0 then output = output .. "^" end
output = output .. texture output = output .. layers[rank]
end
end end
return output return output
end end
@ -115,13 +137,13 @@ function mcl_skins.update_player_skin(player)
return return
end end
local skin = mcl_skins.players[player] local skin = mcl_skins.player_skins[player]
mcl_player.player_set_skin(player, mcl_skins.compile_skin(skin)) mcl_player.player_set_skin(player, mcl_skins.compile_skin(skin))
local slim_arms local slim_arms
if skin.simple_skins_id then if skin.simple_skins_id then
slim_arms = mcl_skins.simple_skins[skin.simple_skins_id].slim_arms slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms
else else
slim_arms = skin.slim_arms slim_arms = skin.slim_arms
end end
@ -131,33 +153,35 @@ end
-- Load player skin on join -- Load player skin on join
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
local function table_get_random(t)
return t[math.random(#t)]
end
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
-- If the player moves a slider and then quickly exits the game, form_send_job gets saved. if not mcl_skins.texture_to_simple_skin[skin.simple_skins_id] then
-- This should never have been put in with the skin data in the first place. skin.simple_skins_id = nil
skin.form_send_job = nil end
mcl_skins.players[player] = skin mcl_skins.player_skins[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[player] = skin mcl_skins.player_skins[player] = skin
end end
mcl_skins.players[player].simple_skins_id = nil mcl_skins.player_formspecs[player] = {
active_tab = "skin",
page_num = 1
}
if #mcl_skins.simple_skins > 0 then if #mcl_skins.simple_skins > 0 then
local skin_id = tonumber(player:get_meta():get_string("mcl_skins:skin_id")) local skin_id = tonumber(player:get_meta():get_string("mcl_skins:skin_id"))
if skin_id and mcl_skins.simple_skins[skin_id] then if skin_id and mcl_skins.simple_skins[skin_id] then
mcl_skins.players[player].simple_skins_id = skin_id local texture = mcl_skins.simple_skins[skin_id].texture
mcl_skins.player_skins[player].simple_skins_id = texture
end end
end end
mcl_skins.save(player) mcl_skins.save(player)
@ -165,33 +189,17 @@ minetest.register_on_joinplayer(function(player)
end) end)
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
mcl_skins.players[player] = nil mcl_skins.player_skins[player] = nil
mcl_skins.player_formspecs[player] = nil
end) end)
function mcl_skins.show_formspec(player, active_tab, page_num) function mcl_skins.show_formspec(player)
local skin = mcl_skins.players[player] local formspec_data = mcl_skins.player_formspecs[player]
local default = #mcl_skins.simple_skins > 0 and "skin" or "template" local skin = mcl_skins.player_skins[player]
active_tab = active_tab or default local active_tab = formspec_data.active_tab
page_num = page_num or 1 local page_num = formspec_data.page_num
local page_count local formspec = "formspec_version[3]size[14.2,11]"
if page_num < 1 then page_num = 1 end
if mcl_skins[active_tab] then
page_count = math.ceil(#mcl_skins[active_tab] / 16)
if page_num > page_count then
page_num = page_count
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
page_num = 1
page_count = 1
end
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
if tab == active_tab then if tab == active_tab then
@ -201,21 +209,23 @@ 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] .. "]" "style[" .. tab .. ";content_offset=16,0]" ..
"button[0.3," .. y .. ";4,0.8;" .. tab .. ";" .. mcl_skins.tab_descriptions[tab] .. "]" ..
"image[0.4," .. y + 0.1 .. ";0.6,0.6;mcl_skins_icons.png^[verticalframe:11:" .. i - 1 .. "]"
if skin.simple_skins_id then break end if skin.simple_skins_id then break end
end end
local slim_arms local slim_arms
if skin.simple_skins_id then if skin.simple_skins_id then
slim_arms = mcl_skins.simple_skins[skin.simple_skins_id].slim_arms slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms
else else
slim_arms = skin.slim_arms slim_arms = skin.slim_arms
end end
local mesh = slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d" 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[11,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]" ",blank.png,blank.png;0,180;false;true;0,0]"
@ -226,21 +236,22 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
"style_type[button;bgcolor=#00000000]" "style_type[button;bgcolor=#00000000]"
local skin = table.copy(skin) local skin = table.copy(skin)
local skin_id = skin.simple_skins_id or -1 local simple_skins_id = skin.simple_skins_id
skin.simple_skins_id = nil skin.simple_skins_id = nil
mcl_skins.simple_skins[-1] = {
local skins = table.copy(mcl_skins.simple_skins)
skins[-1] = {
slim_arms = skin.slim_arms, slim_arms = skin.slim_arms,
texture = mcl_skins.compile_skin(skin), texture = mcl_skins.compile_skin(skin),
} }
simple_skins_id = simple_skins_id or
mcl_skins.simple_skins[-1].texture
for i = page_start, page_end do for i = page_start, page_end do
local skin = skins[i] local skin = mcl_skins.simple_skins[i]
local j = i - page_start - 1 local j = i - page_start - 1
local mesh = skin.slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d" 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 x = 4.5 + (j + 1) % 4 * 1.6
local y = 0.3 + math.floor((j + 1) / 4) * 3.1 local y = 0.3 + math.floor((j + 1) / 4) * 3.1
formspec = formspec .. formspec = formspec ..
@ -248,7 +259,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
skin.texture .. skin.texture ..
",blank.png,blank.png;0,180;false;true;0,0]" ",blank.png,blank.png;0,180;false;true;0,0]"
if skin_id == i then if simple_skins_id == skin.texture then
formspec = formspec .. formspec = formspec ..
"style[" .. i .. "style[" .. i ..
";bgcolor=;bgimg=mcl_skins_select_overlay.png;" .. ";bgcolor=;bgimg=mcl_skins_select_overlay.png;" ..
@ -259,21 +270,21 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
end end
if page_start == -1 then if page_start == -1 then
formspec = formspec .. "image[3.85,1;0.8,0.8;mcl_skins_button.png]" formspec = formspec .. "image[4.85,1;0.8,0.8;mcl_skins_button.png]"
end end
elseif active_tab == "template" then elseif active_tab == "template" then
formspec = formspec .. formspec = formspec ..
"model[4,2;2,3;player_mesh;mcl_armor_character.b3d;" .. "model[5,2;2,3;player_mesh;mcl_armor_character.b3d;" ..
mcl_skins.compile_skin(mcl_skins.steve) .. mcl_skins.compile_skin(mcl_skins.steve) ..
",blank.png,blank.png;0,180;false;true;0,0]" .. ",blank.png,blank.png;0,180;false;true;0,0]" ..
"button[4,5.2;2,0.8;steve;" .. S("Select") .. "]" .. "button[5,5.2;2,0.8;steve;" .. S("Select") .. "]" ..
"model[6.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" .. "model[7.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" ..
mcl_skins.compile_skin(mcl_skins.alex) .. mcl_skins.compile_skin(mcl_skins.alex) ..
",blank.png,blank.png;0,180;false;true;0,0]" .. ",blank.png,blank.png;0,180;false;true;0,0]" ..
"button[6.5,5.2;2,0.8;alex;" .. S("Select") .. "]" "button[7.5,5.2;2,0.8;alex;" .. S("Select") .. "]"
elseif mcl_skins[active_tab] then elseif mcl_skins[active_tab] then
formspec = formspec .. formspec = formspec ..
@ -308,7 +319,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
end end
i = i - 1 i = i - 1
local x = 3.5 + i % 4 * 1.6 local x = 4.5 + i % 4 * 1.6
local y = 0.3 + math.floor(i / 4) * 1.6 local y = 0.3 + math.floor(i / 4) * 1.6
formspec = formspec .. formspec = formspec ..
"model[" .. x .. "," .. y .. "model[" .. x .. "," .. y ..
@ -325,11 +336,12 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
formspec = formspec .. "button[" .. x .. "," .. y .. ";1.5,1.5;" .. texture .. ";]" formspec = formspec .. "button[" .. x .. "," .. y .. ";1.5,1.5;" .. texture .. ";]"
end end
elseif active_tab == "arm" then elseif active_tab == "arm" then
local x = skin.slim_arms and 4.7 or 3.6 local x = skin.slim_arms and 5.7 or 4.6
formspec = formspec .. formspec = formspec ..
"image_button[3.6,0.3;1,1;mcl_skins_thick_arms.png;thick_arms;]" .. "image_button[4.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_arms;]" .. "image_button[5.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]" .. "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;]" "button[" .. x .. ",0.3;1,1;arm;]"
end end
@ -343,7 +355,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
for i, colorspec in pairs(colors) do for i, colorspec in pairs(colors) do
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 = 4.6 + i % 6 * 0.9
local y = 8 + math.floor(i / 6) * 0.9 local y = 8 + math.floor(i / 6) * 0.9
formspec = formspec .. formspec = formspec ..
"image_button[" .. x .. "," .. y .. "image_button[" .. x .. "," .. y ..
@ -353,7 +365,8 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
if selected_color == colorspec then if selected_color == colorspec then
formspec = formspec .. formspec = formspec ..
"style[" .. color .. "style[" .. color ..
";bgcolor=;bgimg=mcl_skins_select_overlay.png;bgimg_middle=14,14;bgimg_pressed=mcl_skins_select_overlay.png]" .. ";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 .. ";]" "button[" .. x .. "," .. y .. ";0.8,0.8;" .. color .. ";]"
end end
@ -365,7 +378,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
local green = math.floor(selected_color / 0x100) - 0xff0000 - red * 0x100 local green = math.floor(selected_color / 0x100) - 0xff0000 - red * 0x100
local blue = selected_color - 0xff000000 - red * 0x10000 - green * 0x100 local blue = selected_color - 0xff000000 - red * 0x10000 - green * 0x100
formspec = formspec .. formspec = formspec ..
"container[9.2,8]" .. "container[10.2,8]" ..
"scrollbaroptions[min=0;max=255;smallstep=20]" .. "scrollbaroptions[min=0;max=255;smallstep=20]" ..
"box[0.4,0;2.49,0.38;red]" .. "box[0.4,0;2.49,0.38;red]" ..
@ -387,23 +400,30 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
end end
end end
local page_count = 1
if mcl_skins[active_tab] then
page_count = math.ceil(#mcl_skins[active_tab] / 16)
elseif active_tab == "skin" then
page_count = math.ceil((#mcl_skins.simple_skins + 2) / 8)
end
if page_num > 1 then if page_num > 1 then
formspec = formspec .. formspec = formspec ..
"image_button[3.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]" "image_button[4.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]"
end end
if page_num < page_count then if page_num < page_count then
formspec = formspec .. formspec = formspec ..
"image_button[8.8,6.7;1,1;mcl_skins_arrow.png;next_page;]" "image_button[9.8,6.7;1,1;mcl_skins_arrow.png;next_page;]"
end end
if page_count > 1 then if page_count > 1 then
formspec = formspec .. formspec = formspec ..
"label[6.3,7.2;" .. page_num .. " / " .. page_count .. "]" "label[7.3,7.2;" .. page_num .. " / " .. page_count .. "]"
end end
local player_name = player:get_player_name() 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:skins", formspec)
end end
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)
@ -412,23 +432,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
return false return false
end end
if formname ~= "mcl_skins:skins" then return false end
if not formname:find("^mcl_skins:") then return false end local formspec_data = mcl_skins.player_formspecs[player]
local _, _, active_tab, page_num = formname:find("^mcl_skins:(%a+)_(%d+)") local active_tab = formspec_data.active_tab
local active_tab_found = false
for _, tab in pairs(mcl_skins.tab_names) do
if tab == active_tab then active_tab_found = true end
end
active_tab = active_tab_found and active_tab or "template"
if not page_num or not active_tab then return true end
page_num = math.floor(tonumber(page_num) or 1)
-- Cancel formspec resend after scrollbar move -- Cancel formspec resend after scrollbar move
if mcl_skins.players[player].form_send_job then if formspec_data.form_send_job then
mcl_skins.players[player].form_send_job:cancel() formspec_data.form_send_job:cancel()
mcl_skins.players[player].form_send_job = nil formspec_data.form_send_job = nil
end end
if fields.quit then if fields.quit then
@ -437,34 +449,52 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
if fields.alex then if fields.alex then
mcl_skins.players[player] = table.copy(mcl_skins.alex) mcl_skins.player_skins[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)
return true return true
elseif fields.steve then elseif fields.steve then
mcl_skins.players[player] = table.copy(mcl_skins.steve) mcl_skins.player_skins[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)
return true return true
end end
for i, tab in pairs(mcl_skins.tab_names) do for i, tab in pairs(mcl_skins.tab_names) do
if fields[tab] then if fields[tab] then
mcl_skins.show_formspec(player, tab, page_num) formspec_data.active_tab = tab
formspec_data.page_num = 1
mcl_skins.show_formspec(player)
return true return true
end end
end end
local skin = mcl_skins.players[player] local skin = mcl_skins.player_skins[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
local page_num = formspec_data.page_num
page_num = page_num + 1 page_num = page_num + 1
mcl_skins.show_formspec(player, active_tab, page_num)
local page_count
if active_tab == "skin" then
page_count = math.ceil((#mcl_skins.simple_skins + 2) / 8)
else
page_count = math.ceil(#mcl_skins[active_tab] / 16)
end
if page_num > page_count then
page_num = page_count
end
formspec_data.page_num = page_num
mcl_skins.show_formspec(player)
return true return true
elseif fields.previous_page then elseif fields.previous_page then
local page_num = formspec_data.page_num
page_num = page_num - 1 page_num = page_num - 1
mcl_skins.show_formspec(player, active_tab, page_num) if page_num < 1 then page_num = 1 end
formspec_data.page_num = page_num
mcl_skins.show_formspec(player)
return true return true
end end
@ -475,7 +505,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
skin.slim_arms = true skin.slim_arms = true
end end
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)
return true return true
end end
@ -496,12 +526,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].form_send_job = minetest.after(0.2, function() formspec_data.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)
mcl_skins.players[player].form_send_job = nil formspec_data.form_send_job = nil
end end
end) end)
return true return true
@ -517,31 +547,30 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
if field and active_tab == "skin" then if field and active_tab == "skin" then
local skin_id = tonumber(field) local index = tonumber(field)
skin_id = skin_id and math.floor(skin_id) or 0 index = index and math.floor(index) or 0
mcl_skins.simple_skins[-1].texture = nil
if if
#mcl_skins.simple_skins > 0 and #mcl_skins.simple_skins > 0 and
skin_id >= -1 and skin_id <= #mcl_skins.simple_skins index >= -1 and index <= #mcl_skins.simple_skins
then then
if skin_id == -1 then skin_id = nil end skin.simple_skins_id = mcl_skins.simple_skins[index].texture
skin.simple_skins_id = skin_id
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)
end end
return true return true
end end
-- See if field is a texture -- See if field is a texture
if field and mcl_skins[active_tab] then if
for i, texture in pairs(mcl_skins[active_tab]) do field and mcl_skins[active_tab] and
if texture == field then table.indexof(mcl_skins[active_tab], field) ~= -1
skin[active_tab] = texture then
skin[active_tab] = field
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)
return true return true
end end
end
end
-- See if field is a color -- See if field is a color
local number = tonumber(field) local number = tonumber(field)
@ -550,7 +579,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if color and color >= 0 and color <= 0xffffffff then if color and color >= 0 and color <= 0xffffffff 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)
return true return true
end end
end end
@ -559,15 +588,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end) end)
local function init() local function init()
local function file_exists(name)
local f = io.open(name)
if not f then
return false
end
f:close()
return true
end
local f = io.open(minetest.get_modpath("mcl_skins") .. "/list.json") local f = io.open(minetest.get_modpath("mcl_skins") .. "/list.json")
assert(f, "Can't open the file list.json") assert(f, "Can't open the file list.json")
local data = f:read("*all") local data = f:read("*all")
@ -590,6 +610,16 @@ local function init()
mcl_skins.alex.top_color = 0xff346840 mcl_skins.alex.top_color = 0xff346840
mcl_skins.alex.bottom_color = 0xff383532 mcl_skins.alex.bottom_color = 0xff383532
mcl_skins.alex.slim_arms = true mcl_skins.alex.slim_arms = true
mcl_skins.register_simple_skin({
index = 0,
texture = "character.png"
})
mcl_skins.register_simple_skin({
index = 1,
texture = "mcl_skins_character_1.png",
slim_arms = true
})
end end
init() init()

View File

@ -3,7 +3,8 @@
"type": "footwear", "type": "footwear",
"texture": "mcl_skins_footwear_1.png", "texture": "mcl_skins_footwear_1.png",
"steve": true, "steve": true,
"alex": true "alex": true,
"rank": 55
}, },
{ {
"type": "footwear", "type": "footwear",
@ -198,6 +199,12 @@
"texture": "mcl_skins_bottom_4.png", "texture": "mcl_skins_bottom_4.png",
"mask": "mcl_skins_bottom_4_mask.png" "mask": "mcl_skins_bottom_4_mask.png"
}, },
{
"type": "bottom",
"texture": "mcl_skins_bottom_5.png",
"mask": "mcl_skins_bottom_5_mask.png",
"rank": 65
},
{ {
"type": "top", "type": "top",
"texture": "mcl_skins_top_1.png", "texture": "mcl_skins_top_1.png",

View File

@ -21,6 +21,9 @@ mcl_skins_bottom_3.png
mcl_skins_eye_7.png mcl_skins_eye_7.png
mcl_skins_mouth_7.png mcl_skins_mouth_7.png
mcl_skins_hair_10.png mcl_skins_hair_10.png
mcl_skins_hair_6.png
mcl_skins_eye_6.png
mcl_skins_bottom_5.png
Original work by MrRar Original work by MrRar
License: CC BY-SA 4.0 License: CC BY-SA 4.0
@ -66,13 +69,6 @@ Author: hansuke123. Adapted for mcl_skins by MrRar.
License: CC BY-SA 3.0 License: CC BY-SA 3.0
Source: http://minetest.fensta.bplaced.net/#!page:1,filtertype:Id,filter:291 Source: http://minetest.fensta.bplaced.net/#!page:1,filtertype:Id,filter:291
mcl_skins_hair_6.png
mcl_skins_eye_6.png
Name: Mumbo Jumbo
Author: ZestyZachary
License: CC 0 (1.0)
Source: http://minetest.fensta.bplaced.net/#!page:1,filtertype:Id,filter:2100
mcl_skins_eye_4.png mcl_skins_eye_4.png
Name: lisa Name: lisa
Author: hansuke123 Author: hansuke123

View File

@ -14,7 +14,9 @@ function mcl_skins.get_skin_list()
for _, game_mode in pairs({"_crea", "_surv"}) do for _, game_mode in pairs({"_crea", "_surv"}) do
for _, base in pairs(mcl_skins.base) do for _, base in pairs(mcl_skins.base) do
for _, base_color in pairs(mcl_skins.base_color) do for _, base_color in pairs(mcl_skins.base_color) do
local id = base:gsub(".png$", "") .. minetest.colorspec_to_colorstring(base_color):gsub("#", "") local id = base:gsub(".png$", "")
.. minetest.colorspec_to_colorstring(base_color):gsub("#", "")
local female = { local female = {
texture = make_texture(base, base_color), texture = make_texture(base, base_color),
slim_arms = true, slim_arms = true,
@ -36,7 +38,8 @@ function mcl_skins.get_skin_list()
table.insert(list, { table.insert(list, {
texture = skin.texture, texture = skin.texture,
slim_arms = skin.slim_arms, slim_arms = skin.slim_arms,
id = skin.texture:gsub(".png$", "") .. (skin.slim_arms and "_female" or "_male") .. game_mode, id = skin.texture:gsub(".png$", "")
.. (skin.slim_arms and "_female" or "_male") .. game_mode,
creative = game_mode == "_crea" creative = game_mode == "_crea"
}) })
end end
@ -45,10 +48,10 @@ function mcl_skins.get_skin_list()
end end
function mcl_skins.get_node_id_by_player(player) function mcl_skins.get_node_id_by_player(player)
local skin = mcl_skins.players[player] local skin = mcl_skins.player_skins[player]
local simple_skin = skin.simple_skins_id local simple_skin = skin.simple_skins_id
if simple_skin then if simple_skin then
skin = mcl_skins.simple_skins[skin.simple_skins_id] skin = mcl_skins.texture_to_simple_skin[skin.simple_skins_id]
end end
local creative = minetest.is_creative_enabled(player:get_player_name()) local creative = minetest.is_creative_enabled(player:get_player_name())
local append = (skin.slim_arms and "_female" or "_male") .. (creative and "_crea" or "_surv") local append = (skin.slim_arms and "_female" or "_male") .. (creative and "_crea" or "_surv")

View File

@ -1,3 +0,0 @@
name = "Steve",
author = "%TEXTURE_PACK_AUTHOR%",
gender = "male",

View File

@ -1,3 +0,0 @@
name = "Alex",
author = "%TEXTURE_PACK_AUTHOR%",
gender = "female",

View File

@ -1,5 +1,5 @@
local function init_simple_skins() local function init_simple_skins()
local id, f, data, skin = 0 local id, f, data, skin = 2
local mod_path = minetest.get_modpath("mcl_skins") local mod_path = minetest.get_modpath("mcl_skins")
while true do while true do
@ -35,18 +35,13 @@ local function init_simple_skins()
end end
-- add metadata to list -- add metadata to list
mcl_skins.simple_skins[id] = { mcl_skins.register_simple_skin({
index = id,
texture = skin, texture = skin,
slim_arms = data and data.gender == "female", slim_arms = data and data.gender == "female",
} })
id = id + 1 id = id + 1
end end
if #mcl_skins.simple_skins > 0 then
table.insert(mcl_skins.tab_names, 1, "skin")
else
mcl_skins.simple_skins = {}
end
end end
init_simple_skins() init_simple_skins()

View File

@ -0,0 +1,3 @@
To add custom skins to the game, please use the mcl_custom_skins mod.
Download it from https://git.minetest.land/mineclone2/mcl_custom_skins
Support for adding custom skins to mcl_skins will be removed in a future MineClone2 release.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 B

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 680 B

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 B

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 B

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 B

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 B

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 B

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 B