VoxeLibre/mods/PLAYER/mcl_skins/edit_skin.lua

745 lines
22 KiB
Lua
Raw Permalink Normal View History

2022-08-29 20:09:00 +02:00
local S = minetest.get_translator("mcl_skins")
local color_to_string = minetest.colorspec_to_colorstring
2023-05-18 19:48:41 +02:00
local EDIT_SKIN_KEY = -1 -- The key used for edit skin in the mcl_skins.simple_skins table
2022-08-29 20:09:00 +02:00
mcl_skins = {
2022-09-06 19:51:43 +02:00
simple_skins = {},
2023-04-27 05:01:37 +02:00
texture_to_simple_skin = {},
2023-12-17 14:54:25 +01:00
item_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear", "cape"},
2023-12-03 11:33:15 +01:00
tab_names = {"skin", "template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear", "cape"},
2022-08-29 20:09:00 +02:00
tab_descriptions = {
template = S("Templates"),
arm = S("Arm size"),
base = S("Bases"),
footwear = S("Footwears"),
eye = S("Eyes"),
mouth = S("Mouths"),
bottom = S("Bottoms"),
top = S("Tops"),
hair = S("Hairs"),
2022-09-06 19:51:43 +02:00
headwear = S("Headwears"),
skin = S("Skins"),
2023-12-03 11:33:15 +01:00
cape = S("Capes")
2022-08-29 20:09:00 +02:00
},
2023-12-17 14:54:25 +01:00
cape = {},
2023-05-18 19:48:41 +02:00
template1 = {}, -- Stores edit skin values for template1
template2 = {}, -- Stores edit skin values for template2
2022-08-29 20:09:00 +02:00
base = {}, -- List of base textures
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
-- Base color is separate to keep the number of junk nodes registered in check
base_color = {0xffeeb592, 0xffb47a57, 0xff8d471d},
color = {
0xff613915, -- 1 Dark brown
2022-08-29 20:09:00 +02:00
0xff97491b, -- 2 Medium brown
0xffb17050, -- 3 Light brown
0xffe2bc7b, -- 4 Beige
0xff706662, -- 5 Gray
0xff151515, -- 6 Black
0xffc21c1c, -- 7 Red
0xff178c32, -- 8 Green
2022-08-29 20:09:00 +02:00
0xffae2ad3, -- 9 Plum
0xffebe8e4, -- 10 White
0xffe3dd26, -- 11 Yellow
0xff449acc, -- 12 Light blue
0xff124d87, -- 13 Dark blue
2022-08-29 20:09:00 +02:00
0xfffc0eb3, -- 14 Pink
0xffd0672a, -- 15 Orange
2022-08-29 20:09:00 +02:00
},
footwear = {},
mouth = {},
eye = {},
bottom = {},
top = {},
hair = {},
headwear = {},
masks = {},
preview_rotations = {},
2023-04-27 05:01:37 +02:00
ranks = {},
player_skins = {},
player_formspecs = {},
2022-08-29 20:09:00 +02:00
}
local player_skins = mcl_skins.player_skins
local function get_player_skins(player)
local player_skins = player_skins[player]
if player_skins then return player_skins end
local skin = player:get_meta():get_string("mcl_skins:skin")
if skin then
skin = minetest.deserialize(skin)
end
if skin then
if not mcl_skins.texture_to_simple_skin[skin.simple_skins_id] then
skin.simple_skins_id = nil
end
mcl_skins.player_skins[player] = skin
else
if math.random() > 0.5 then
skin = table.copy(mcl_skins.template1)
else
skin = table.copy(mcl_skins.template2)
end
mcl_skins.player_skins[player] = skin
end
mcl_skins.player_formspecs[player] = {
active_tab = "skin",
page_num = 1
}
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
local texture = mcl_skins.simple_skins[skin_id].texture
local player_skins = get_player_skins(player)
player_skins.simple_skins_id = texture
end
end
mcl_skins.save(player)
mcl_skins.update_player_skin(player)
return mcl_skins.player_skins[player]
end
2022-08-29 20:09:00 +02:00
function mcl_skins.register_item(item)
assert(mcl_skins[item.type], "Skin item type " .. item.type .. " does not exist.")
2023-12-17 14:54:25 +01:00
if item.type == "cape" then
local func = item.selector_func
if type(func) == "string" then
func = loadstring(func)()
end
table.insert(mcl_skins.cape, {name=item.name, selector_func=func, mask=item.mask})
mcl_skins.masks[item.name] = item.mask
return
end
2022-08-29 20:09:00 +02:00
local texture = item.texture or "blank.png"
2023-12-17 14:54:25 +01:00
2023-05-18 19:48:41 +02:00
if item.template1 then
mcl_skins.template1[item.type] = texture
2022-08-29 20:09:00 +02:00
end
2023-12-10 07:29:45 +01:00
2023-05-18 19:48:41 +02:00
if item.template2 then
mcl_skins.template2[item.type] = texture
2022-08-29 20:09:00 +02:00
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
table.insert(mcl_skins[item.type], texture)
mcl_skins.masks[texture] = item.mask
2023-04-27 05:01:37 +02:00
mcl_skins.preview_rotations[texture] = item.preview_rotation
mcl_skins.ranks[texture] = item.rank
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)
2022-08-29 20:09:00 +02:00
end
2023-04-27 05:01:37 +02:00
mcl_skins.texture_to_simple_skin[skin.texture] = skin
2022-08-29 20:09:00 +02:00
end
function mcl_skins.save(player)
2023-04-27 05:01:37 +02:00
local skin = mcl_skins.player_skins[player]
2022-08-29 20:09:00 +02:00
if not skin then return end
2023-04-27 05:01:37 +02:00
2022-09-06 19:51:43 +02:00
local meta = player:get_meta()
meta:set_string("mcl_skins:skin", minetest.serialize(skin))
2023-04-27 05:01:37 +02:00
-- Clear out the old way of storing the simple skin ID
meta:set_string("mcl_skins:skin_id", "")
2022-08-29 20:09:00 +02:00
end
minetest.register_chatcommand("skin", {
description = S("Open skin configuration screen."),
privs = {},
2023-05-18 19:48:41 +02:00
func = function(name, param)
local player = minetest.get_player_by_name(name)
local formspec_data = mcl_skins.player_formspecs[player]
local active_tab = formspec_data.active_tab
local page_num = formspec_data.page_num
mcl_skins.show_formspec(player, active_tab, page_num)
end
2022-08-29 20:09:00 +02:00
})
2022-09-06 19:51:43 +02:00
function mcl_skins.compile_skin(skin)
2023-04-27 05:01:37 +02:00
if not skin then return "blank.png" end
2022-09-06 19:51:43 +02:00
if skin.simple_skins_id then
2023-04-27 05:01:37 +02:00
return skin.simple_skins_id
2022-08-29 20:09:00 +02:00
end
2023-04-27 05:01:37 +02:00
local ranks = {}
local layers = {}
for i, item in ipairs(mcl_skins.item_names) do
2022-09-06 19:51:43 +02:00
local texture = skin[item]
2023-04-27 05:01:37 +02:00
local layer = ""
local rank = mcl_skins.ranks[texture] or i * 10
2022-08-29 20:09:00 +02:00
if texture and texture ~= "blank.png" then
2022-09-06 19:51:43 +02:00
if skin[item .. "_color"] and mcl_skins.masks[texture] then
local color = color_to_string(skin[item .. "_color"])
2023-04-27 05:01:37 +02:00
layer = "(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)"
2022-08-29 20:09:00 +02:00
end
2023-04-27 05:01:37 +02:00
if #layer > 0 then layer = layer .. "^" end
layer = layer .. texture
layers[rank] = layer
table.insert(ranks, rank)
2022-08-29 20:09:00 +02:00
end
end
2023-04-27 05:01:37 +02:00
table.sort(ranks)
local output = ""
for i, rank in ipairs(ranks) do
if #output > 0 then output = output .. "^" end
output = output .. layers[rank]
end
2022-08-29 20:09:00 +02:00
return output
end
function mcl_skins.update_player_skin(player)
if not player then
return
end
2023-12-10 07:29:45 +01:00
local skin = get_player_skins(player)
local skinval = mcl_skins.compile_skin(skin)
2022-08-29 20:09:00 +02:00
if not skin.cape then skin.cape = "blank.png" end
if player:get_inventory():get_stack("armor", 3):get_name() == "mcl_armor:elytra" then
skinval = skinval:gsub("%^" .. skin.cape, "")
-- don't render the "normal" cape on players while wearing the elytra.
-- this is NOT used when the player puts an elytra on, see register.lua in mcl_armor for that.
-- this is used when a player joins or changes something regarding their skin.
end
mcl_player.player_set_skin(player, skinval)
2023-12-10 07:29:45 +01:00
2022-09-06 19:51:43 +02:00
local slim_arms
if skin.simple_skins_id then
2023-04-27 05:01:37 +02:00
slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms
2022-09-06 19:51:43 +02:00
else
slim_arms = skin.slim_arms
end
local model = slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d"
2022-08-29 20:09:00 +02:00
mcl_player.player_set_model(player, model)
end
-- Load player skin on join
minetest.register_on_joinplayer(function(player)
get_player_skins(player)
2022-08-29 20:09:00 +02:00
end)
minetest.register_on_leaveplayer(function(player)
2023-04-27 05:01:37 +02:00
mcl_skins.player_skins[player] = nil
mcl_skins.player_formspecs[player] = nil
2022-08-29 20:09:00 +02:00
end)
2024-01-13 12:17:09 +01:00
local function calculate_page_count(tab, player)
2023-05-18 19:48:41 +02:00
if tab == "skin" then
return math.ceil((#mcl_skins.simple_skins + 2) / 8)
2023-12-17 14:54:25 +01:00
elseif tab == "cape" then
2024-01-13 12:17:09 +01:00
local player_capes = 0
for _, cape in pairs(mcl_skins.cape) do
if type(cape.selector_func) == "nil" or cape.selector_func(player) then
player_capes = player_capes + 1
end
end
return math.ceil((player_capes + 1) / 5) -- add one so the player can select no cape as well
2023-05-18 19:48:41 +02:00
elseif mcl_skins[tab] then
return math.ceil(#mcl_skins[tab] / 16)
end
return 1
end
function mcl_skins.show_formspec(player, active_tab, page_num)
2023-04-27 05:01:37 +02:00
local formspec_data = mcl_skins.player_formspecs[player]
local skin = get_player_skins(player)
2023-05-18 19:48:41 +02:00
formspec_data.active_tab = active_tab
2023-12-10 07:29:45 +01:00
2024-01-13 12:17:09 +01:00
local page_count = calculate_page_count(active_tab, player)
2023-05-18 19:48:41 +02:00
if page_num < 1 then page_num = 1 end
if page_num > page_count then page_num = page_count end
formspec_data.page_num = page_num
2023-12-10 07:29:45 +01:00
2023-04-27 05:01:37 +02:00
local formspec = "formspec_version[3]size[14.2,11]"
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
for i, tab in pairs(mcl_skins.tab_names) do
if tab == active_tab then
formspec = formspec ..
"style[" .. tab .. ";bgcolor=green]"
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
local y = 0.3 + (i - 1) * 0.8
formspec = formspec ..
2023-04-27 05:01:37 +02:00
"style[" .. tab .. ";content_offset=16,0]" ..
"button[0.3," .. y .. ";4,0.8;" .. tab .. ";" .. mcl_skins.tab_descriptions[tab] .. "]" ..
2023-12-03 11:33:15 +01:00
"image[0.4," .. y + 0.1 .. ";0.6,0.6;mcl_skins_icons.png^[verticalframe:12:" .. i - 1 .. "]"
2023-12-10 07:29:45 +01:00
2022-09-06 19:51:43 +02:00
if skin.simple_skins_id then break end
2022-08-29 20:09:00 +02:00
end
2023-12-10 07:29:45 +01:00
2022-09-06 19:51:43 +02:00
local slim_arms
if skin.simple_skins_id then
2023-04-27 05:01:37 +02:00
slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms
2022-09-06 19:51:43 +02:00
else
slim_arms = skin.slim_arms
end
local mesh = slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d"
2022-08-29 20:09:00 +02:00
formspec = formspec ..
2023-04-27 05:01:37 +02:00
"model[11,0.3;3,7;player_mesh;" .. mesh .. ";" ..
2022-08-29 20:09:00 +02:00
mcl_skins.compile_skin(skin) ..
2022-09-15 19:51:40 +02:00
",blank.png,blank.png;0,180;false;true;0,0]"
2022-08-29 20:09:00 +02:00
2023-12-17 14:54:25 +01:00
local cape_tab = active_tab == "cape"
2022-09-06 19:51:43 +02:00
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]"
2023-04-27 05:01:37 +02:00
2022-09-06 19:51:43 +02:00
local skin = table.copy(skin)
2023-04-27 05:01:37 +02:00
local simple_skins_id = skin.simple_skins_id
2022-09-06 19:51:43 +02:00
skin.simple_skins_id = nil
2023-05-18 19:48:41 +02:00
mcl_skins.simple_skins[EDIT_SKIN_KEY] = {
2022-09-06 19:51:43 +02:00
slim_arms = skin.slim_arms,
texture = mcl_skins.compile_skin(skin),
}
2023-04-27 05:01:37 +02:00
simple_skins_id = simple_skins_id or
2023-05-18 19:48:41 +02:00
mcl_skins.simple_skins[EDIT_SKIN_KEY].texture
2023-12-10 07:29:45 +01:00
2022-09-06 19:51:43 +02:00
for i = page_start, page_end do
2023-04-27 05:01:37 +02:00
local skin = mcl_skins.simple_skins[i]
2022-09-06 19:51:43 +02:00
local j = i - page_start - 1
2023-04-27 05:01:37 +02:00
local mesh = skin.slim_arms and "mcl_armor_character_female.b3d" or
"mcl_armor_character.b3d"
2023-12-10 07:29:45 +01:00
2023-04-27 05:01:37 +02:00
local x = 4.5 + (j + 1) % 4 * 1.6
2022-09-06 19:51:43 +02:00
local y = 0.3 + math.floor((j + 1) / 4) * 3.1
2023-12-10 07:29:45 +01:00
2022-09-06 19:51:43 +02:00
formspec = formspec ..
"model[" .. x .. "," .. y .. ";1.5,3;player_mesh;" .. mesh .. ";" ..
skin.texture ..
2022-09-15 19:51:40 +02:00
",blank.png,blank.png;0,180;false;true;0,0]"
2023-12-10 07:29:45 +01:00
2023-04-27 05:01:37 +02:00
if simple_skins_id == skin.texture then
2022-09-06 19:51:43 +02:00
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
2023-12-10 07:29:45 +01:00
2023-05-18 19:48:41 +02:00
if page_start == EDIT_SKIN_KEY then
2023-04-27 05:01:37 +02:00
formspec = formspec .. "image[4.85,1;0.8,0.8;mcl_skins_button.png]"
2022-09-06 19:51:43 +02:00
end
elseif active_tab == "template" then
2022-08-29 20:09:00 +02:00
formspec = formspec ..
2023-04-27 05:01:37 +02:00
"model[5,2;2,3;player_mesh;mcl_armor_character.b3d;" ..
2023-05-18 19:48:41 +02:00
mcl_skins.compile_skin(mcl_skins.template1) ..
2022-09-15 19:51:40 +02:00
",blank.png,blank.png;0,180;false;true;0,0]" ..
2022-08-29 20:09:00 +02:00
2023-05-18 19:48:41 +02:00
"button[5,5.2;2,0.8;template1;" .. S("Select") .. "]" ..
2022-08-29 20:09:00 +02:00
2023-04-27 05:01:37 +02:00
"model[7.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" ..
2023-05-18 19:48:41 +02:00
mcl_skins.compile_skin(mcl_skins.template2) ..
2022-09-15 19:51:40 +02:00
",blank.png,blank.png;0,180;false;true;0,0]" ..
2023-12-10 07:29:45 +01:00
2023-05-18 19:48:41 +02:00
"button[7.5,5.2;2,0.8;template2;" .. S("Select") .. "]"
2023-12-03 11:33:15 +01:00
2023-12-17 14:54:25 +01:00
elseif cape_tab then
local possize = {{"6,2;1,2", "5.5,4.2;2,0.8"}, {"9,2;1,2","8.5,4.2;2,0.8"}, {"6,7;1,2","5.5,9.2;2,0.8"}, {"9,7;1,2","8.5,9.2;2,0.8"},{"12,7;1,2","11.5,9.2;2,0.8"}}
2024-01-13 12:17:09 +01:00
local player_capes = {} -- contains all capes the player is allowed to wear
for _, cape in pairs (mcl_skins.cape) do
if type(cape.selector_func) == "nil" or cape.selector_func(player) then
table.insert(player_capes, cape)
end
end
2023-12-03 11:33:15 +01:00
2024-01-13 12:17:09 +01:00
local slot_offset = 0
2023-12-17 14:54:25 +01:00
if page_num == 1 then
formspec = formspec ..
"label[6,3;" .. S("(None)") .. "]"..
"button[5.5,4.2;2,0.8;nocape;" .. S("Select") .. "]"
2024-01-13 12:17:09 +01:00
slot_offset = 1
2023-12-17 14:54:25 +01:00
end
2023-12-03 11:33:15 +01:00
2024-01-13 12:17:09 +01:00
local array_start = page_num * 5 - 4
local index_offset = page_num == 1 and 1 or 2
for slot = 1 + slot_offset, page_num ~= page_count and 5 or (#player_capes % 5 == 0 and 1 or #player_capes % 5) + slot_offset do
local cape = player_capes[array_start + slot - slot_offset - index_offset]
2023-12-17 14:54:25 +01:00
local pos = possize[slot]
2024-01-13 12:17:09 +01:00
formspec = formspec ..
"image[" .. possize[slot][1] .. ";" .. cape.name ..".png]"..
"button[" .. possize[slot][2] .. ";" .. cape.name ..";" .. S("Select") .. "]"
2023-12-17 14:54:25 +01:00
end
2023-12-03 11:33:15 +01:00
2022-08-29 20:09:00 +02:00
elseif mcl_skins[active_tab] then
formspec = formspec ..
2022-09-06 19:51:43 +02:00
"style_type[button;bgcolor=#00000000]"
2022-08-29 20:09:00 +02:00
local textures = mcl_skins[active_tab]
local page_start = (page_num - 1) * 16 + 1
local page_end = math.min(page_start + 16 - 1, #textures)
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
for j = page_start, page_end do
local i = j - page_start + 1
local texture = textures[j]
local preview = mcl_skins.masks[skin.base] .. "^[colorize:gray^" .. skin.base
local color = color_to_string(skin[active_tab .. "_color"])
local mask = mcl_skins.masks[texture]
if color and mask then
preview = preview .. "^(" .. mask .. "^[colorize:" .. color .. ":alpha)"
end
preview = preview .. "^" .. texture
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
local mesh = "mcl_skins_head.obj"
if active_tab == "top" then
mesh = "mcl_skins_top.obj"
elseif active_tab == "bottom" or active_tab == "footwear" then
mesh = "mcl_skins_bottom.obj"
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
local rot_x = -10
local rot_y = 20
if mcl_skins.preview_rotations[texture] then
rot_x = mcl_skins.preview_rotations[texture].x
rot_y = mcl_skins.preview_rotations[texture].y
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
i = i - 1
2023-04-27 05:01:37 +02:00
local x = 4.5 + i % 4 * 1.6
2022-08-29 20:09:00 +02:00
local y = 0.3 + math.floor(i / 4) * 1.6
formspec = formspec ..
"model[" .. x .. "," .. y ..
";1.5,1.5;" .. mesh .. ";" .. mesh .. ";" ..
preview ..
2022-09-15 19:51:40 +02:00
";" .. rot_x .. "," .. rot_y .. ";false;false;0,0]"
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
if skin[active_tab] == texture then
formspec = formspec ..
2022-09-06 19:51:43 +02:00
"style[" .. texture ..
";bgcolor=;bgimg=mcl_skins_select_overlay.png;" ..
"bgimg_pressed=mcl_skins_select_overlay.png;bgimg_middle=14,14]"
2022-08-29 20:09:00 +02:00
end
2022-09-06 19:51:43 +02:00
formspec = formspec .. "button[" .. x .. "," .. y .. ";1.5,1.5;" .. texture .. ";]"
2022-08-29 20:09:00 +02:00
end
elseif active_tab == "arm" then
2023-04-27 05:01:37 +02:00
local x = skin.slim_arms and 5.7 or 4.6
2022-08-29 20:09:00 +02:00
formspec = formspec ..
2023-04-27 05:01:37 +02:00
"image_button[4.6,0.3;1,1;mcl_skins_thick_arms.png;thick_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]" ..
2022-09-06 19:51:43 +02:00
"button[" .. x .. ",0.3;1,1;arm;]"
2022-08-29 20:09:00 +02:00
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
if skin[active_tab .. "_color"] then
local colors = mcl_skins.color
if active_tab == "base" then colors = mcl_skins.base_color end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
local tab_color = active_tab .. "_color"
local selected_color = skin[tab_color]
for i, colorspec in pairs(colors) do
local color = color_to_string(colorspec)
i = i - 1
2023-04-27 05:01:37 +02:00
local x = 4.6 + i % 6 * 0.9
2022-08-29 20:09:00 +02:00
local y = 8 + math.floor(i / 6) * 0.9
formspec = formspec ..
"image_button[" .. x .. "," .. y ..
";0.8,0.8;blank.png^[noalpha^[colorize:" ..
2022-09-06 19:51:43 +02:00
color .. ":alpha;" .. colorspec .. ";]"
2023-12-10 07:29:45 +01:00
2022-09-06 19:51:43 +02:00
if selected_color == colorspec then
formspec = formspec ..
"style[" .. color ..
2023-04-27 05:01:37 +02:00
";bgcolor=;bgimg=mcl_skins_select_overlay.png;bgimg_middle=14,14;" ..
"bgimg_pressed=mcl_skins_select_overlay.png]" ..
2022-09-06 19:51:43 +02:00
"button[" .. x .. "," .. y .. ";0.8,0.8;" .. color .. ";]"
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
if not (active_tab == "base") then
-- Bitwise Operations !?!?!
local red = math.floor(selected_color / 0x10000) - 0xff00
local green = math.floor(selected_color / 0x100) - 0xff0000 - red * 0x100
local blue = selected_color - 0xff000000 - red * 0x10000 - green * 0x100
formspec = formspec ..
2023-04-27 05:01:37 +02:00
"container[10.2,8]" ..
2022-08-29 20:09:00 +02:00
"scrollbaroptions[min=0;max=255;smallstep=20]" ..
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
"box[0.4,0;2.49,0.38;red]" ..
"label[0.2,0.2;-]" ..
"scrollbar[0.4,0;2.5,0.4;horizontal;red;" .. red .."]" ..
"label[2.9,0.2;+]" ..
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
"box[0.4,0.6;2.49,0.38;green]" ..
"label[0.2,0.8;-]" ..
"scrollbar[0.4,0.6;2.5,0.4;horizontal;green;" .. green .."]" ..
"label[2.9,0.8;+]" ..
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
"box[0.4,1.2;2.49,0.38;blue]" ..
"label[0.2,1.4;-]" ..
"scrollbar[0.4,1.2;2.5,0.4;horizontal;blue;" .. blue .. "]" ..
"label[2.9,1.4;+]" ..
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
"container_end[]"
end
end
2023-04-27 05:01:37 +02:00
2022-08-29 20:09:00 +02:00
if page_num > 1 then
if cape_tab then
2023-12-17 14:54:25 +01:00
formspec = formspec ..
"image_button[4.5,0.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]"
else
formspec = formspec ..
"image_button[4.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]"
end
2022-08-29 20:09:00 +02:00
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
if page_num < page_count then
2023-12-17 14:54:25 +01:00
if cape_tab then
formspec = formspec ..
"image_button[9.8,0.7;1,1;mcl_skins_arrow.png;next_page;]"
else
formspec = formspec ..
"image_button[9.8,6.7;1,1;mcl_skins_arrow.png;next_page;]"
end
2022-08-29 20:09:00 +02:00
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
if page_count > 1 then
2023-12-17 14:54:25 +01:00
if cape_tab then
formspec = formspec ..
"label[7.3,1.2;" .. page_num .. " / " .. page_count .. "]"
else
formspec = formspec ..
"label[7.3,7.2;" .. page_num .. " / " .. page_count .. "]"
end
2022-08-29 20:09:00 +02:00
end
2022-09-06 19:51:43 +02:00
local player_name = player:get_player_name()
2023-04-27 05:01:37 +02:00
minetest.show_formspec(player_name, "mcl_skins:skins", formspec)
2022-08-29 20:09:00 +02:00
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
2023-05-18 19:48:41 +02:00
local formspec_data = mcl_skins.player_formspecs[player]
local active_tab = formspec_data.active_tab
local page_num = formspec_data.page_num
2022-08-29 20:09:00 +02:00
if fields.__mcl_skins then
2023-05-18 19:48:41 +02:00
mcl_skins.show_formspec(player, active_tab, page_num)
2022-08-29 20:09:00 +02:00
return false
end
2023-04-27 05:01:37 +02:00
if formname ~= "mcl_skins:skins" then return false end
2022-08-29 20:09:00 +02:00
-- Cancel formspec resend after scrollbar move
2023-04-27 05:01:37 +02:00
if formspec_data.form_send_job then
formspec_data.form_send_job:cancel()
formspec_data.form_send_job = nil
2022-08-29 20:09:00 +02:00
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
if fields.quit then
mcl_skins.save(player)
return true
end
2023-05-18 19:48:41 +02:00
if fields.template2 then
mcl_skins.player_skins[player] = table.copy(mcl_skins.template2)
2022-08-29 20:09:00 +02:00
mcl_skins.update_player_skin(player)
2023-05-18 19:48:41 +02:00
mcl_skins.show_formspec(player, active_tab, page_num)
2022-08-29 20:09:00 +02:00
return true
2023-05-18 19:48:41 +02:00
elseif fields.template1 then
mcl_skins.player_skins[player] = table.copy(mcl_skins.template1)
2022-08-29 20:09:00 +02:00
mcl_skins.update_player_skin(player)
2023-05-18 19:48:41 +02:00
mcl_skins.show_formspec(player, active_tab, page_num)
2022-08-29 20:09:00 +02:00
return true
2023-12-03 11:33:15 +01:00
elseif fields.nocape then
local player_skins = get_player_skins(player)
player_skins.cape = "blank.png"
2023-12-03 11:33:15 +01:00
mcl_skins.update_player_skin(player)
2023-12-17 15:06:09 +01:00
mcl_armor.update(player) --update elytra cape
2024-01-13 12:17:09 +01:00
mcl_skins.show_formspec(player, active_tab, page_num)
2023-12-03 11:33:15 +01:00
return true
2023-12-17 14:54:25 +01:00
elseif active_tab == "cape" then
for cape_index = ((page_num - 1) * 5) + 1, math.min(#mcl_skins.cape, page_num * 5) do
local cape = mcl_skins.cape[cape_index]
if fields[cape.name] then
local player_skins = get_player_skins(player)
player_skins.cape = cape.mask -- the actual overlay image
2023-12-17 14:54:25 +01:00
mcl_skins.update_player_skin(player)
2023-12-17 15:06:09 +01:00
mcl_armor.update(player) --update elytra cape
2024-01-13 12:17:09 +01:00
mcl_skins.show_formspec(player, active_tab, page_num)
2023-12-17 14:54:25 +01:00
return true
end
end
2022-08-29 20:09:00 +02:00
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
for i, tab in pairs(mcl_skins.tab_names) do
if fields[tab] then
2023-05-18 19:48:41 +02:00
mcl_skins.show_formspec(player, tab, 1)
2022-08-29 20:09:00 +02:00
return true
end
end
2023-12-10 07:29:45 +01:00
local skin = get_player_skins(player)
2022-08-29 20:09:00 +02:00
if not skin then return true end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
if fields.next_page then
page_num = page_num + 1
2023-05-18 19:48:41 +02:00
mcl_skins.show_formspec(player, active_tab, page_num)
2022-08-29 20:09:00 +02:00
return true
elseif fields.previous_page then
page_num = page_num - 1
2023-05-18 19:48:41 +02:00
mcl_skins.show_formspec(player, active_tab, page_num)
2022-08-29 20:09:00 +02:00
return true
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
if active_tab == "arm" then
if fields.thick_arms then
skin.slim_arms = false
elseif fields.slim_arms then
skin.slim_arms = true
end
mcl_skins.update_player_skin(player)
2023-05-18 19:48:41 +02:00
mcl_skins.show_formspec(player, active_tab, page_num)
2022-08-29 20:09:00 +02:00
return true
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
if
skin[active_tab .. "_color"] and (
fields.red and fields.red:find("^CHG") or
fields.green and fields.green:find("^CHG") or
fields.blue and fields.blue:find("^CHG")
)
then
local red = fields.red:gsub("%a%a%a:", "")
local green = fields.green:gsub("%a%a%a:", "")
local blue = fields.blue:gsub("%a%a%a:", "")
red = tonumber(red) or 0
green = tonumber(green) or 0
blue = tonumber(blue) or 0
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
local color = 0xff000000 + red * 0x10000 + green * 0x100 + blue
if color >= 0 and color <= 0xffffffff then
-- We delay resedning the form because otherwise it will break dragging scrollbars
2023-04-27 05:01:37 +02:00
formspec_data.form_send_job = minetest.after(0.2, function()
2022-08-29 20:09:00 +02:00
if player and player:is_player() then
skin[active_tab .. "_color"] = color
mcl_skins.update_player_skin(player)
2023-05-18 19:48:41 +02:00
mcl_skins.show_formspec(player, active_tab, page_num)
2023-04-27 05:01:37 +02:00
formspec_data.form_send_job = nil
2022-08-29 20:09:00 +02:00
end
end)
return true
end
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
local field
for f, value in pairs(fields) do
if value == "" then
field = f
break
end
end
2023-12-10 07:29:45 +01:00
2022-09-06 19:51:43 +02:00
if field and active_tab == "skin" then
2023-04-27 05:01:37 +02:00
local index = tonumber(field)
index = index and math.floor(index) or 0
2023-05-18 19:48:41 +02:00
mcl_skins.simple_skins[EDIT_SKIN_KEY].texture = nil
2022-09-06 19:51:43 +02:00
if
#mcl_skins.simple_skins > 0 and
2023-05-18 19:48:41 +02:00
index >= EDIT_SKIN_KEY and index <= #mcl_skins.simple_skins
2022-09-06 19:51:43 +02:00
then
2023-04-27 05:01:37 +02:00
skin.simple_skins_id = mcl_skins.simple_skins[index].texture
2022-09-06 19:51:43 +02:00
mcl_skins.update_player_skin(player)
2023-05-18 19:48:41 +02:00
mcl_skins.show_formspec(player, active_tab, page_num)
2022-09-06 19:51:43 +02:00
end
return true
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
-- See if field is a texture
2023-04-27 05:01:37 +02:00
if
field and mcl_skins[active_tab] and
table.indexof(mcl_skins[active_tab], field) ~= -1
then
skin[active_tab] = field
mcl_skins.update_player_skin(player)
2023-05-18 19:48:41 +02:00
mcl_skins.show_formspec(player, active_tab, page_num)
2023-04-27 05:01:37 +02:00
return true
2022-08-29 20:09:00 +02:00
end
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
-- See if field is a color
local number = tonumber(field)
if number and skin[active_tab .. "_color"] then
local color = math.floor(number)
if color and color >= 0 and color <= 0xffffffff then
skin[active_tab .. "_color"] = color
mcl_skins.update_player_skin(player)
2023-05-18 19:48:41 +02:00
mcl_skins.show_formspec(player, active_tab, page_num)
2022-08-29 20:09:00 +02:00
return true
end
end
return true
end)
local function init()
local f = io.open(minetest.get_modpath("mcl_skins") .. "/list.json")
assert(f, "Can't open the file list.json")
local data = f:read("*all")
assert(data, "Can't read data from list.json")
local json, error = minetest.parse_json(data)
assert(json, error)
f:close()
2023-12-10 07:29:45 +01:00
2022-08-29 20:09:00 +02:00
for _, item in pairs(json) do
mcl_skins.register_item(item)
end
2023-05-18 19:48:41 +02:00
mcl_skins.template1.base_color = mcl_skins.base_color[2]
mcl_skins.template1.hair_color = 0xff5d473b
mcl_skins.template1.top_color = 0xff993535
mcl_skins.template1.bottom_color = 0xff644939
mcl_skins.template1.slim_arms = false
2023-12-17 14:54:25 +01:00
mcl_skins.template1.cape = "blank.png"
2023-12-10 07:29:45 +01:00
2023-05-18 19:48:41 +02:00
mcl_skins.template2.base_color = mcl_skins.base_color[1]
mcl_skins.template2.hair_color = 0xff715d57
mcl_skins.template2.top_color = 0xff346840
mcl_skins.template2.bottom_color = 0xff383532
mcl_skins.template2.slim_arms = true
2023-12-17 14:54:25 +01:00
mcl_skins.template2.cape = "blank.png"
2023-04-27 05:01:37 +02:00
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
})
2022-08-29 20:09:00 +02:00
end
init()
2023-12-17 14:54:25 +01:00
local keep_inventory = vl_tuning.setting("gamerule:keepInventory")
minetest.register_on_respawnplayer(function(player)
if not keep_inventory[1] then
2023-12-17 14:54:25 +01:00
mcl_skins.update_player_skin(player) -- ensures players have their cape again after dying with an elytra
end
end)