diff --git a/mods/ITEMS/mcl_armor/register.lua b/mods/ITEMS/mcl_armor/register.lua index c7fa91475..f4f1fb4d0 100644 --- a/mods/ITEMS/mcl_armor/register.lua +++ b/mods/ITEMS/mcl_armor/register.lua @@ -227,5 +227,27 @@ minetest.register_tool("mcl_armor:elytra", { on_place = mcl_armor.equip_on_use, on_secondary_use = mcl_armor.equip_on_use, _mcl_armor_element = "torso", - _mcl_armor_texture = "mcl_armor_elytra.png" + _mcl_armor_texture = function(obj, itemstack) + if obj:is_player() then + local cape = mcl_skins.player_skins[obj].cape + if cape ~= "blank.png" then + return cape:gsub("_body", "_elytra") + end + end + return "mcl_armor_elytra.png" + end, + _on_equip = function(obj, itemstack) + if not obj:is_player() then return end + local cape = mcl_skins.player_skins[obj].cape + if cape ~= "blank.png" then + local skinval = mcl_player.player_get_skin(obj) + skinval = skinval:gsub("%^" .. cape, "") + mcl_player.player_set_skin(obj, skinval) + -- this doesn't mess with the data mcl_skins has, so when mcl_skins reloads (which happens when the elytra is unequipped), the normal cape returns + end + end, + _on_unequip = function(obj, itemstack) + if not obj:is_player() then return end + mcl_skins.update_player_skin(obj) + end }) diff --git a/mods/PLAYER/mcl_player/init.lua b/mods/PLAYER/mcl_player/init.lua index 9dbd1f724..fb3400329 100644 --- a/mods/PLAYER/mcl_player/init.lua +++ b/mods/PLAYER/mcl_player/init.lua @@ -129,6 +129,11 @@ function mcl_player.player_set_skin(player, texture) update_player_textures(player) end +function mcl_player.player_get_skin(player) + local name = player:get_player_name() + return player_textures[name][1] +end + function mcl_player.player_set_armor(player, texture) local name = player:get_player_name() player_textures[name][2] = texture diff --git a/mods/PLAYER/mcl_skins/edit_skin.lua b/mods/PLAYER/mcl_skins/edit_skin.lua index 706c08461..94866c87d 100644 --- a/mods/PLAYER/mcl_skins/edit_skin.lua +++ b/mods/PLAYER/mcl_skins/edit_skin.lua @@ -5,8 +5,8 @@ local EDIT_SKIN_KEY = -1 -- The key used for edit skin in the mcl_skins.simple_s mcl_skins = { simple_skins = {}, texture_to_simple_skin = {}, - item_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"}, - tab_names = {"skin", "template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"}, + item_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear", "cape"}, + tab_names = {"skin", "template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear", "cape"}, tab_descriptions = { template = S("Templates"), arm = S("Arm size"), @@ -19,11 +19,13 @@ mcl_skins = { hair = S("Hairs"), headwear = S("Headwears"), skin = S("Skins"), + cape = S("Capes") }, + cape = {}, template1 = {}, -- Stores edit skin values for template1 template2 = {}, -- Stores edit skin values for template2 base = {}, -- List of base textures - + -- Base color is separate to keep the number of junk nodes registered in check base_color = {0xffeeb592, 0xffb47a57, 0xff8d471d}, color = { @@ -59,15 +61,29 @@ mcl_skins = { function mcl_skins.register_item(item) assert(mcl_skins[item.type], "Skin item type " .. item.type .. " does not exist.") + + 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 + local texture = item.texture or "blank.png" + if item.template1 then mcl_skins.template1[item.type] = texture end - + if item.template2 then mcl_skins.template2[item.type] = texture end - + table.insert(mcl_skins[item.type], texture) mcl_skins.masks[texture] = item.mask mcl_skins.preview_rotations[texture] = item.preview_rotation @@ -143,11 +159,19 @@ function mcl_skins.update_player_skin(player) if not player then return end - - local skin = mcl_skins.player_skins[player] - mcl_player.player_set_skin(player, mcl_skins.compile_skin(skin)) - + local skin = mcl_skins.player_skins[player] + local skinval = mcl_skins.compile_skin(skin) + + 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) + local slim_arms if skin.simple_skins_id then slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms @@ -200,9 +224,17 @@ minetest.register_on_leaveplayer(function(player) mcl_skins.player_formspecs[player] = nil end) -local function calculate_page_count(tab) +local function calculate_page_count(tab, player) if tab == "skin" then return math.ceil((#mcl_skins.simple_skins + 2) / 8) + elseif tab == "cape" then + 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 elseif mcl_skins[tab] then return math.ceil(#mcl_skins[tab] / 16) end @@ -213,29 +245,29 @@ function mcl_skins.show_formspec(player, active_tab, page_num) local formspec_data = mcl_skins.player_formspecs[player] local skin = mcl_skins.player_skins[player] formspec_data.active_tab = active_tab - - local page_count = calculate_page_count(active_tab) + + local page_count = calculate_page_count(active_tab, player) 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 - + local formspec = "formspec_version[3]size[14.2,11]" - + for i, tab in pairs(mcl_skins.tab_names) do if tab == active_tab then formspec = formspec .. "style[" .. tab .. ";bgcolor=green]" end - + local y = 0.3 + (i - 1) * 0.8 formspec = formspec .. "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 .. "]" - + "image[0.4," .. y + 0.1 .. ";0.6,0.6;mcl_skins_icons.png^[verticalframe:12:" .. i - 1 .. "]" + if skin.simple_skins_id then break end end - + local slim_arms if skin.simple_skins_id then slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms @@ -249,6 +281,9 @@ function mcl_skins.show_formspec(player, active_tab, page_num) mcl_skins.compile_skin(skin) .. ",blank.png,blank.png;0,180;false;true;0,0]" + + local cape_tab = active_tab == "cape" + 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) @@ -264,21 +299,21 @@ function mcl_skins.show_formspec(player, active_tab, page_num) } simple_skins_id = simple_skins_id or mcl_skins.simple_skins[EDIT_SKIN_KEY].texture - + for i = page_start, page_end do local skin = mcl_skins.simple_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 = 4.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]" - + if simple_skins_id == skin.texture then formspec = formspec .. "style[" .. i .. @@ -288,7 +323,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num) formspec = formspec .. "button[" .. x .. "," .. y .. ";1.5,3;" .. i .. ";]" end - + if page_start == EDIT_SKIN_KEY then formspec = formspec .. "image[4.85,1;0.8,0.8;mcl_skins_button.png]" end @@ -303,16 +338,46 @@ function mcl_skins.show_formspec(player, active_tab, page_num) "model[7.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" .. mcl_skins.compile_skin(mcl_skins.template2) .. ",blank.png,blank.png;0,180;false;true;0,0]" .. - + "button[7.5,5.2;2,0.8;template2;" .. S("Select") .. "]" - + + 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"}} + 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 + + local slot_offset = 0 + + if page_num == 1 then + formspec = formspec .. + "label[6,3;" .. S("(None)") .. "]".. + "button[5.5,4.2;2,0.8;nocape;" .. S("Select") .. "]" + slot_offset = 1 + end + + 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] + local pos = possize[slot] + + formspec = formspec .. + "image[" .. possize[slot][1] .. ";" .. cape.name ..".png]".. + "button[" .. possize[slot][2] .. ";" .. cape.name ..";" .. S("Select") .. "]" + end + elseif mcl_skins[active_tab] then formspec = formspec .. "style_type[button;bgcolor=#00000000]" local textures = mcl_skins[active_tab] local page_start = (page_num - 1) * 16 + 1 local page_end = math.min(page_start + 16 - 1, #textures) - + for j = page_start, page_end do local i = j - page_start + 1 local texture = textures[j] @@ -323,21 +388,21 @@ function mcl_skins.show_formspec(player, active_tab, page_num) preview = preview .. "^(" .. mask .. "^[colorize:" .. color .. ":alpha)" end preview = preview .. "^" .. texture - + 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 - + 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 - + i = i - 1 local x = 4.5 + i % 4 * 1.6 local y = 0.3 + math.floor(i / 4) * 1.6 @@ -346,7 +411,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num) ";1.5,1.5;" .. mesh .. ";" .. mesh .. ";" .. preview .. ";" .. rot_x .. "," .. rot_y .. ";false;false;0,0]" - + if skin[active_tab] == texture then formspec = formspec .. "style[" .. texture .. @@ -365,11 +430,11 @@ function mcl_skins.show_formspec(player, active_tab, page_num) "button[" .. x .. ",0.3;1,1;arm;]" end - + if skin[active_tab .. "_color"] then local colors = mcl_skins.color if active_tab == "base" then colors = mcl_skins.base_color end - + local tab_color = active_tab .. "_color" local selected_color = skin[tab_color] for i, colorspec in pairs(colors) do @@ -381,7 +446,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num) "image_button[" .. x .. "," .. y .. ";0.8,0.8;blank.png^[noalpha^[colorize:" .. color .. ":alpha;" .. colorspec .. ";]" - + if selected_color == colorspec then formspec = formspec .. "style[" .. color .. @@ -389,9 +454,9 @@ function mcl_skins.show_formspec(player, active_tab, page_num) "bgimg_pressed=mcl_skins_select_overlay.png]" .. "button[" .. x .. "," .. y .. ";0.8,0.8;" .. color .. ";]" end - + end - + if not (active_tab == "base") then -- Bitwise Operations !?!?! local red = math.floor(selected_color / 0x10000) - 0xff00 @@ -400,39 +465,54 @@ function mcl_skins.show_formspec(player, active_tab, page_num) formspec = formspec .. "container[10.2,8]" .. "scrollbaroptions[min=0;max=255;smallstep=20]" .. - + "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;+]" .. - + "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;+]" .. - + "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;+]" .. - + "container_end[]" end end if page_num > 1 then - formspec = formspec .. - "image_button[4.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]" + if cape_tab then + 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 end - + if page_num < page_count then - formspec = formspec .. - "image_button[9.8,6.7;1,1;mcl_skins_arrow.png;next_page;]" + 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 end - + if page_count > 1 then - formspec = formspec .. - "label[7.3,7.2;" .. page_num .. " / " .. page_count .. "]" + 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 end local player_name = player:get_player_name() @@ -456,7 +536,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) formspec_data.form_send_job:cancel() formspec_data.form_send_job = nil end - + if fields.quit then mcl_skins.save(player) return true @@ -472,18 +552,35 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) mcl_skins.update_player_skin(player) mcl_skins.show_formspec(player, active_tab, page_num) return true + elseif fields.nocape then + mcl_skins.player_skins[player].cape = "blank.png" + mcl_skins.update_player_skin(player) + mcl_armor.update(player) --update elytra cape + mcl_skins.show_formspec(player, active_tab, page_num) + return true + 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 + mcl_skins.player_skins[player].cape = cape.mask -- the actual overlay image + mcl_skins.update_player_skin(player) + mcl_armor.update(player) --update elytra cape + mcl_skins.show_formspec(player, active_tab, page_num) + return true + end + end end - + for i, tab in pairs(mcl_skins.tab_names) do if fields[tab] then mcl_skins.show_formspec(player, tab, 1) return true end end - + local skin = mcl_skins.player_skins[player] if not skin then return true end - + if fields.next_page then page_num = page_num + 1 mcl_skins.show_formspec(player, active_tab, page_num) @@ -493,7 +590,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) mcl_skins.show_formspec(player, active_tab, page_num) return true end - + if active_tab == "arm" then if fields.thick_arms then skin.slim_arms = false @@ -504,7 +601,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) mcl_skins.show_formspec(player, active_tab, page_num) return true end - + if skin[active_tab .. "_color"] and ( fields.red and fields.red:find("^CHG") or @@ -518,7 +615,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) red = tonumber(red) or 0 green = tonumber(green) or 0 blue = tonumber(blue) or 0 - + 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 @@ -533,7 +630,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) return true end end - + local field for f, value in pairs(fields) do if value == "" then @@ -541,7 +638,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) break end end - + if field and active_tab == "skin" then local index = tonumber(field) index = index and math.floor(index) or 0 @@ -556,7 +653,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end return true end - + -- See if field is a texture if field and mcl_skins[active_tab] and @@ -567,7 +664,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) mcl_skins.show_formspec(player, active_tab, page_num) return true end - + -- See if field is a color local number = tonumber(field) if number and skin[active_tab .. "_color"] then @@ -591,7 +688,7 @@ local function init() local json, error = minetest.parse_json(data) assert(json, error) f:close() - + for _, item in pairs(json) do mcl_skins.register_item(item) end @@ -600,12 +697,14 @@ local function init() mcl_skins.template1.top_color = 0xff993535 mcl_skins.template1.bottom_color = 0xff644939 mcl_skins.template1.slim_arms = false - + mcl_skins.template1.cape = "blank.png" + 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 + mcl_skins.template2.cape = "blank.png" mcl_skins.register_simple_skin({ index = 0, @@ -619,3 +718,9 @@ local function init() end init() + +if not minetest.settings:get_bool("mcl_keepInventory", false) then + minetest.register_on_respawnplayer(function(player) + mcl_skins.update_player_skin(player) -- ensures players have their cape again after dying with an elytra + end) +end \ No newline at end of file diff --git a/mods/PLAYER/mcl_skins/list.json b/mods/PLAYER/mcl_skins/list.json index dc7afbfe1..1c0b106e9 100644 --- a/mods/PLAYER/mcl_skins/list.json +++ b/mods/PLAYER/mcl_skins/list.json @@ -263,5 +263,29 @@ "mask": "mcl_skins_base_1_mask.png", "template1": true, "template2": true + }, + { + "type": "cape", + "name": "mtcape", + "mask": "mtcape_body.png", + "selector_func" : null + }, + { + "type": "cape", + "name": "slimecape", + "mask": "slimecape_body.png", + "selector_func" : null + }, + { + "type": "cape", + "name": "ghastcape", + "mask": "ghastcape_body.png", + "selector_func" : null + }, + { + "type": "cape", + "name": "mclcape", + "mask": "mclcape_body.png", + "selector_func" : null } ] diff --git a/mods/PLAYER/mcl_skins/locale/template.txt b/mods/PLAYER/mcl_skins/locale/template.txt index 12ba740d5..96160e2d8 100644 --- a/mods/PLAYER/mcl_skins/locale/template.txt +++ b/mods/PLAYER/mcl_skins/locale/template.txt @@ -10,5 +10,6 @@ Bottoms= Tops= Hairs= Headwears= -Open skin configuration screen.= +Open skin configuration screen.= Select= +Capes= diff --git a/textures/ghastcape.png b/textures/ghastcape.png new file mode 100644 index 000000000..6f6df86c3 Binary files /dev/null and b/textures/ghastcape.png differ diff --git a/textures/ghastcape_body.png b/textures/ghastcape_body.png new file mode 100644 index 000000000..51bb46478 Binary files /dev/null and b/textures/ghastcape_body.png differ diff --git a/textures/ghastcape_elytra.png b/textures/ghastcape_elytra.png new file mode 100644 index 000000000..d05fe46a5 Binary files /dev/null and b/textures/ghastcape_elytra.png differ diff --git a/textures/mcl_skins_icons.png b/textures/mcl_skins_icons.png index f0e7e93d8..a67fc58c1 100644 Binary files a/textures/mcl_skins_icons.png and b/textures/mcl_skins_icons.png differ diff --git a/textures/mclcape.png b/textures/mclcape.png new file mode 100644 index 000000000..0e8a4b9a5 Binary files /dev/null and b/textures/mclcape.png differ diff --git a/textures/mclcape_body.png b/textures/mclcape_body.png new file mode 100644 index 000000000..9332de221 Binary files /dev/null and b/textures/mclcape_body.png differ diff --git a/textures/mclcape_elytra.png b/textures/mclcape_elytra.png new file mode 100644 index 000000000..405501456 Binary files /dev/null and b/textures/mclcape_elytra.png differ diff --git a/textures/mtcape.png b/textures/mtcape.png new file mode 100644 index 000000000..119e12f55 Binary files /dev/null and b/textures/mtcape.png differ diff --git a/textures/mtcape_body.png b/textures/mtcape_body.png new file mode 100644 index 000000000..3e36d3971 Binary files /dev/null and b/textures/mtcape_body.png differ diff --git a/textures/mtcape_elytra.png b/textures/mtcape_elytra.png new file mode 100644 index 000000000..441e22ec1 Binary files /dev/null and b/textures/mtcape_elytra.png differ diff --git a/textures/slimecape.png b/textures/slimecape.png new file mode 100644 index 000000000..d6492723d Binary files /dev/null and b/textures/slimecape.png differ diff --git a/textures/slimecape_body.png b/textures/slimecape_body.png new file mode 100644 index 000000000..9b89d6a6c Binary files /dev/null and b/textures/slimecape_body.png differ diff --git a/textures/slimecape_elytra.png b/textures/slimecape_elytra.png new file mode 100644 index 000000000..f3b979a74 Binary files /dev/null and b/textures/slimecape_elytra.png differ