From 8e6b6393c2c2be879672db9f6f10194f99c93fbf Mon Sep 17 00:00:00 2001 From: Johannes Fritz Date: Mon, 29 Aug 2022 13:09:00 -0500 Subject: [PATCH 1/2] Add advanced skin customization --- mods/HUD/mcl_inventory/creative.lua | 76 +-- mods/HUD/mcl_inventory/init.lua | 100 ++-- mods/ITEMS/mcl_maps/init.lua | 43 +- mods/PLAYER/mcl_meshhand/init.lua | 126 ++--- mods/PLAYER/mcl_player/init.lua | 2 +- mods/PLAYER/mcl_skins/.gitignore | 4 - mods/PLAYER/mcl_skins/LICENSE.txt | 2 +- mods/PLAYER/mcl_skins/README.md | 82 ++- mods/PLAYER/mcl_skins/edit_skin.lua | 523 ++++++++++++++++++ mods/PLAYER/mcl_skins/init.lua | 284 +--------- mods/PLAYER/mcl_skins/list.json | 259 +++++++++ mods/PLAYER/mcl_skins/locale/mcl_skins.de.tr | 13 - mods/PLAYER/mcl_skins/locale/mcl_skins.es.tr | 13 - mods/PLAYER/mcl_skins/locale/mcl_skins.fr.tr | 25 +- mods/PLAYER/mcl_skins/locale/mcl_skins.ms.tr | 16 - mods/PLAYER/mcl_skins/locale/mcl_skins.pl.tr | 13 - mods/PLAYER/mcl_skins/locale/mcl_skins.ru.tr | 13 - .../mcl_skins/locale/mcl_skins.zh_TW.tr | 13 - mods/PLAYER/mcl_skins/locale/template.txt | 24 +- mods/PLAYER/mcl_skins/media_credits.txt | 115 ++++ .../mcl_skins/meta/mcl_skins_character.txt | 3 - .../mcl_skins/meta/mcl_skins_character_1.txt | 3 - mods/PLAYER/mcl_skins/mod.conf | 7 +- .../mcl_skins/models/mcl_skins_bottom.obj | 108 ++++ .../mcl_skins/models/mcl_skins_head.obj | 72 +++ .../PLAYER/mcl_skins/models/mcl_skins_top.obj | 174 ++++++ .../mcl_skins/textures/mcl_skins_arrow.png | Bin 0 -> 137 bytes .../mcl_skins/textures/mcl_skins_base_1.png | Bin 0 -> 1136 bytes .../textures/mcl_skins_base_1_mask.png | Bin 0 -> 153 bytes .../mcl_skins/textures/mcl_skins_bottom_1.png | Bin 0 -> 377 bytes .../textures/mcl_skins_bottom_1_mask.png | Bin 0 -> 144 bytes .../mcl_skins/textures/mcl_skins_bottom_2.png | Bin 0 -> 694 bytes .../textures/mcl_skins_bottom_2_mask.png | Bin 0 -> 151 bytes .../mcl_skins/textures/mcl_skins_bottom_3.png | Bin 0 -> 604 bytes .../textures/mcl_skins_bottom_3_mask.png | Bin 0 -> 137 bytes .../mcl_skins/textures/mcl_skins_bottom_4.png | Bin 0 -> 680 bytes .../textures/mcl_skins_bottom_4_mask.png | Bin 0 -> 141 bytes .../mcl_skins/textures/mcl_skins_button.png | Bin 2010 -> 203 bytes .../textures/mcl_skins_character_1.png | Bin 5505 -> 0 bytes .../mcl_skins/textures/mcl_skins_eye_1.png | Bin 0 -> 171 bytes .../mcl_skins/textures/mcl_skins_eye_2.png | Bin 0 -> 131 bytes .../mcl_skins/textures/mcl_skins_eye_3.png | Bin 0 -> 121 bytes .../mcl_skins/textures/mcl_skins_eye_4.png | Bin 0 -> 136 bytes .../mcl_skins/textures/mcl_skins_eye_5.png | Bin 0 -> 107 bytes .../mcl_skins/textures/mcl_skins_eye_6.png | Bin 0 -> 151 bytes .../mcl_skins/textures/mcl_skins_eye_7.png | Bin 0 -> 99 bytes .../textures/mcl_skins_footwear_1.png | Bin 0 -> 927 bytes .../textures/mcl_skins_footwear_2.png | Bin 0 -> 229 bytes .../textures/mcl_skins_footwear_3.png | Bin 0 -> 331 bytes .../mcl_skins/textures/mcl_skins_hair_1.png | Bin 0 -> 484 bytes .../mcl_skins/textures/mcl_skins_hair_10.png | Bin 0 -> 328 bytes .../textures/mcl_skins_hair_10_mask.png | Bin 0 -> 170 bytes .../mcl_skins/textures/mcl_skins_hair_11.png | Bin 0 -> 454 bytes .../textures/mcl_skins_hair_11_mask.png | Bin 0 -> 202 bytes .../textures/mcl_skins_hair_1_mask.png | Bin 0 -> 196 bytes .../mcl_skins/textures/mcl_skins_hair_2.png | Bin 0 -> 490 bytes .../textures/mcl_skins_hair_2_mask.png | Bin 0 -> 169 bytes .../mcl_skins/textures/mcl_skins_hair_3.png | Bin 0 -> 445 bytes .../textures/mcl_skins_hair_3_mask.png | Bin 0 -> 175 bytes .../mcl_skins/textures/mcl_skins_hair_4.png | Bin 0 -> 1097 bytes .../textures/mcl_skins_hair_4_mask.png | Bin 0 -> 196 bytes .../mcl_skins/textures/mcl_skins_hair_5.png | Bin 0 -> 886 bytes .../textures/mcl_skins_hair_5_mask.png | Bin 0 -> 282 bytes .../mcl_skins/textures/mcl_skins_hair_6.png | Bin 0 -> 680 bytes .../textures/mcl_skins_hair_6_mask.png | Bin 0 -> 161 bytes .../mcl_skins/textures/mcl_skins_hair_7.png | Bin 0 -> 576 bytes .../textures/mcl_skins_hair_7_mask.png | Bin 0 -> 195 bytes .../mcl_skins/textures/mcl_skins_hair_8.png | Bin 0 -> 582 bytes .../textures/mcl_skins_hair_8_mask.png | Bin 0 -> 172 bytes .../mcl_skins/textures/mcl_skins_hair_9.png | Bin 0 -> 730 bytes .../textures/mcl_skins_hair_9_mask.png | Bin 0 -> 243 bytes .../textures/mcl_skins_headwear_1.png | Bin 0 -> 648 bytes .../textures/mcl_skins_headwear_2.png | Bin 0 -> 886 bytes .../textures/mcl_skins_headwear_3.png | Bin 0 -> 120 bytes .../textures/mcl_skins_headwear_4.png | Bin 0 -> 125 bytes .../textures/mcl_skins_headwear_5.png | Bin 0 -> 120 bytes .../textures/mcl_skins_headwear_6.png | Bin 0 -> 140 bytes .../textures/mcl_skins_headwear_7.png | Bin 0 -> 291 bytes .../mcl_skins/textures/mcl_skins_mouth_1.png | Bin 0 -> 99 bytes .../mcl_skins/textures/mcl_skins_mouth_2.png | Bin 0 -> 122 bytes .../mcl_skins/textures/mcl_skins_mouth_3.png | Bin 0 -> 139 bytes .../mcl_skins/textures/mcl_skins_mouth_4.png | Bin 0 -> 129 bytes .../mcl_skins/textures/mcl_skins_mouth_5.png | Bin 0 -> 95 bytes .../mcl_skins/textures/mcl_skins_mouth_6.png | Bin 0 -> 99 bytes .../mcl_skins/textures/mcl_skins_mouth_7.png | Bin 0 -> 98 bytes .../textures/mcl_skins_select_overlay.png | Bin 0 -> 167 bytes .../textures/mcl_skins_slim_arms.png | Bin 0 -> 93 bytes .../textures/mcl_skins_thick_arms.png | Bin 0 -> 93 bytes .../mcl_skins/textures/mcl_skins_top_1.png | Bin 0 -> 606 bytes .../mcl_skins/textures/mcl_skins_top_10.png | Bin 0 -> 392 bytes .../textures/mcl_skins_top_10_mask.png | Bin 0 -> 154 bytes .../textures/mcl_skins_top_1_mask.png | Bin 0 -> 131 bytes .../mcl_skins/textures/mcl_skins_top_2.png | Bin 0 -> 568 bytes .../textures/mcl_skins_top_2_mask.png | Bin 0 -> 146 bytes .../mcl_skins/textures/mcl_skins_top_3.png | Bin 0 -> 941 bytes .../textures/mcl_skins_top_3_mask.png | Bin 0 -> 138 bytes .../mcl_skins/textures/mcl_skins_top_4.png | Bin 0 -> 1453 bytes .../textures/mcl_skins_top_4_mask.png | Bin 0 -> 150 bytes .../mcl_skins/textures/mcl_skins_top_5.png | Bin 0 -> 2214 bytes .../textures/mcl_skins_top_5_mask.png | Bin 0 -> 151 bytes .../mcl_skins/textures/mcl_skins_top_6.png | Bin 0 -> 683 bytes .../textures/mcl_skins_top_6_mask.png | Bin 0 -> 161 bytes .../mcl_skins/textures/mcl_skins_top_7.png | Bin 0 -> 960 bytes .../textures/mcl_skins_top_7_mask.png | Bin 0 -> 167 bytes .../mcl_skins/textures/mcl_skins_top_8.png | Bin 0 -> 625 bytes .../textures/mcl_skins_top_8_mask.png | Bin 0 -> 130 bytes .../mcl_skins/textures/mcl_skins_top_9.png | Bin 0 -> 482 bytes .../textures/mcl_skins_top_9_mask.png | Bin 0 -> 166 bytes settingtypes.txt | 4 + 109 files changed, 1550 insertions(+), 567 deletions(-) delete mode 100644 mods/PLAYER/mcl_skins/.gitignore create mode 100644 mods/PLAYER/mcl_skins/edit_skin.lua create mode 100644 mods/PLAYER/mcl_skins/list.json delete mode 100644 mods/PLAYER/mcl_skins/locale/mcl_skins.de.tr delete mode 100644 mods/PLAYER/mcl_skins/locale/mcl_skins.es.tr delete mode 100644 mods/PLAYER/mcl_skins/locale/mcl_skins.ms.tr delete mode 100644 mods/PLAYER/mcl_skins/locale/mcl_skins.pl.tr delete mode 100644 mods/PLAYER/mcl_skins/locale/mcl_skins.ru.tr delete mode 100644 mods/PLAYER/mcl_skins/locale/mcl_skins.zh_TW.tr create mode 100644 mods/PLAYER/mcl_skins/media_credits.txt delete mode 100644 mods/PLAYER/mcl_skins/meta/mcl_skins_character.txt delete mode 100644 mods/PLAYER/mcl_skins/meta/mcl_skins_character_1.txt create mode 100644 mods/PLAYER/mcl_skins/models/mcl_skins_bottom.obj create mode 100644 mods/PLAYER/mcl_skins/models/mcl_skins_head.obj create mode 100644 mods/PLAYER/mcl_skins/models/mcl_skins_top.obj create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_arrow.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_base_1.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_base_1_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_1.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_1_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_2.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_2_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_3.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_3_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_4.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_4_mask.png delete mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_character_1.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_eye_1.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_eye_2.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_eye_3.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_eye_4.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_eye_5.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_eye_6.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_eye_7.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_footwear_1.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_footwear_2.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_footwear_3.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_1.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_10.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_10_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_11.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_11_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_1_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_2.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_2_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_3.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_3_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_4.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_4_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_5.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_5_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_6.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_6_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_7.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_7_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_8.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_8_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_9.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_hair_9_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_1.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_2.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_3.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_4.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_5.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_6.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_7.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_1.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_2.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_3.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_4.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_5.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_6.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_7.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_select_overlay.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_slim_arms.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_thick_arms.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_1.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_10.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_10_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_1_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_2.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_2_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_3.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_3_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_4.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_4_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_5.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_5_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_6.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_6_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_7.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_7_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_8.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_8_mask.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_9.png create mode 100644 mods/PLAYER/mcl_skins/textures/mcl_skins_top_9_mask.png diff --git a/mods/HUD/mcl_inventory/creative.lua b/mods/HUD/mcl_inventory/creative.lua index 4c2faaef6..278ca87b1 100644 --- a/mods/HUD/mcl_inventory/creative.lua +++ b/mods/HUD/mcl_inventory/creative.lua @@ -362,39 +362,49 @@ function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size, local stack_size = get_stack_size(player) -- Survival inventory slots - main_list = "list[current_player;main;0,3.75;9,3;9]".. - mcl_formspec.get_itemslot_bg(0,3.75,9,3).. - -- armor - "list[current_player;armor;2.5,1.3;1,1;1]".. - "list[current_player;armor;2.5,2.75;1,1;2]".. - "list[current_player;armor;5.5,1.3;1,1;3]".. - "list[current_player;armor;5.5,2.75;1,1;4]".. - mcl_formspec.get_itemslot_bg(2.5,1.3,1,1).. - mcl_formspec.get_itemslot_bg(2.5,2.75,1,1).. - mcl_formspec.get_itemslot_bg(5.5,1.3,1,1).. - mcl_formspec.get_itemslot_bg(5.5,2.75,1,1).. - "list[current_player;offhand;1.5,2.025;1,1]".. - mcl_formspec.get_itemslot_bg(1.5,2.025,1,1).. - armor_slot_imgs.. - -- player preview - mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "").. - -- crafting guide button - "image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]".. - "tooltip[__mcl_craftguide;"..F(S("Recipe book")).."]".. - -- help button - "image_button[9,2;1,1;doc_button_icon_lores.png;__mcl_doc;]".. - "tooltip[__mcl_doc;"..F(S("Help")).."]".. - -- skins button - "image_button[9,3;1,1;mcl_skins_button.png;__mcl_skins;]".. - "tooltip[__mcl_skins;"..F(S("Select player skin")).."]".. - -- achievements button - "image_button[9,4;1,1;mcl_achievements_button.png;__mcl_achievements;]".. - --"style_type[image_button;border=;bgimg=;bgimg_pressed=]".. - "tooltip[__mcl_achievements;"..F(S("Achievements")).."]".. - -- switch stack size button - "image_button[9,5;1,1;default_apple.png;__switch_stack;]".. - "label[9.4,5.4;".. F(C("#FFFFFF", stack_size ~= 1 and stack_size or "")) .."]".. - "tooltip[__switch_stack;"..F(S("Switch stack size")).."]" + main_list = "list[current_player;main;0,3.75;9,3;9]" .. + mcl_formspec.get_itemslot_bg(0, 3.75, 9, 3) .. + + -- Armor + "list[current_player;armor;2.5,1.3;1,1;1]" .. + "list[current_player;armor;2.5,2.75;1,1;2]" .. + "list[current_player;armor;5.5,1.3;1,1;3]" .. + "list[current_player;armor;5.5,2.75;1,1;4]" .. + mcl_formspec.get_itemslot_bg(2.5, 1.3, 1, 1) .. + mcl_formspec.get_itemslot_bg(2.5, 2.75, 1, 1) .. + mcl_formspec.get_itemslot_bg(5.5, 1.3, 1, 1) .. + mcl_formspec.get_itemslot_bg(5.5, 2.75, 1, 1) .. + "list[current_player;offhand;1.5,2.025;1,1]" .. + mcl_formspec.get_itemslot_bg(1.5, 2.025, 1, 1) .. + armor_slot_imgs .. + + -- Player preview + mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "") .. + + -- Crafting guide button + "image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]" .. + "tooltip[__mcl_craftguide;"..F(S("Recipe book")) .. "]" .. + + -- Help button + "image_button[9,2;1,1;doc_button_icon_lores.png;__mcl_doc;]" .. + "tooltip[__mcl_doc;" .. F(S("Help")) .. "]" .. + + -- Achievements button + "image_button[9,3;1,1;mcl_achievements_button.png;__mcl_achievements;]" .. + --"style_type[image_button;border=;bgimg=;bgimg_pressed=]" .. + "tooltip[__mcl_achievements;"..F(S("Achievements")) .. "]" .. + + -- Switch stack size button + "image_button[9,4;1,1;default_apple.png;__switch_stack;]" .. + "label[9.4,4.4;" .. F(C("#FFFFFF", stack_size ~= 1 and stack_size or "")) .. "]" .. + "tooltip[__switch_stack;" .. F(S("Switch stack size")) .. "]" + + -- Skins button + if minetest.global_exists("mcl_skins") then + main_list = main_list .. + "image_button[9,5;1,1;mcl_skins_button.png;__mcl_skins;]" .. + "tooltip[__mcl_skins;"..F(S("Select player skin")) .. "]" + end -- For shortcuts listrings = listrings .. diff --git a/mods/HUD/mcl_inventory/init.lua b/mods/HUD/mcl_inventory/init.lua index 1a73e59df..86670a8b3 100644 --- a/mods/HUD/mcl_inventory/init.lua +++ b/mods/HUD/mcl_inventory/init.lua @@ -72,50 +72,62 @@ local function set_inventory(player, armor_change_only) armor_slot_imgs = armor_slot_imgs .. "image[3,2;1,1;mcl_inventory_empty_armor_slot_shield.png]" end - local form = "size[9,8.75]".. - "background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png]".. - mcl_player.get_player_formspec_model(player, 1.0, 0.0, 2.25, 4.5, "").. - --armor - "list[current_player;armor;0,0;1,1;1]".. - "list[current_player;armor;0,1;1,1;2]".. - "list[current_player;armor;0,2;1,1;3]".. - "list[current_player;armor;0,3;1,1;4]".. - mcl_formspec.get_itemslot_bg(0,0,1,1).. - mcl_formspec.get_itemslot_bg(0,1,1,1).. - mcl_formspec.get_itemslot_bg(0,2,1,1).. - mcl_formspec.get_itemslot_bg(0,3,1,1).. - "list[current_player;offhand;3,2;1,1]".. - mcl_formspec.get_itemslot_bg(3,2,1,1).. - armor_slot_imgs.. - -- craft and inventory - "label[0,4;"..F(minetest.colorize("#313131", S("Inventory"))).."]".. - "list[current_player;main;0,4.5;9,3;9]".. - "list[current_player;main;0,7.74;9,1;]".. - "label[4,0.5;"..F(minetest.colorize("#313131", S("Crafting"))).."]".. - "list[current_player;craft;4,1;2,2]".. - "list[current_player;craftpreview;7,1.5;1,1;]".. - mcl_formspec.get_itemslot_bg(0,4.5,9,3).. - mcl_formspec.get_itemslot_bg(0,7.74,9,1).. - mcl_formspec.get_itemslot_bg(4,1,2,2).. - mcl_formspec.get_itemslot_bg(7,1.5,1,1).. - -- crafting guide button - "image_button[4.5,3;1,1;craftguide_book.png;__mcl_craftguide;]".. - "tooltip[__mcl_craftguide;"..F(S("Recipe book")).."]".. - -- help button - "image_button[8,3;1,1;doc_button_icon_lores.png;__mcl_doc;]".. - "tooltip[__mcl_doc;"..F(S("Help")).."]".. - -- skins button - "image_button[3,3;1,1;mcl_skins_button.png;__mcl_skins;]".. - "tooltip[__mcl_skins;"..F(S("Select player skin")).."]".. - -- achievements button - "image_button[7,3;1,1;mcl_achievements_button.png;__mcl_achievements;]".. - "tooltip[__mcl_achievements;"..F(S("Achievements")).."]".. - -- for shortcuts - "listring[current_player;main]".. - "listring[current_player;armor]".. - "listring[current_player;main]" .. - "listring[current_player;craft]" .. - "listring[current_player;main]" + local form = "size[9,8.75]" .. + "background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png]" .. + mcl_player.get_player_formspec_model(player, 1.0, 0.0, 2.25, 4.5, "") .. + + -- Armor + "list[current_player;armor;0,0;1,1;1]" .. + "list[current_player;armor;0,1;1,1;2]" .. + "list[current_player;armor;0,2;1,1;3]" .. + "list[current_player;armor;0,3;1,1;4]" .. + mcl_formspec.get_itemslot_bg(0,0,1,1) .. + mcl_formspec.get_itemslot_bg(0,1,1,1) .. + mcl_formspec.get_itemslot_bg(0,2,1,1) .. + mcl_formspec.get_itemslot_bg(0,3,1,1) .. + "list[current_player;offhand;3,2;1,1]" .. + mcl_formspec.get_itemslot_bg(3,2,1,1) .. + armor_slot_imgs .. + + -- Craft and inventory + "label[0,4;"..F(minetest.colorize("#313131", S("Inventory"))) .. "]" .. + "list[current_player;main;0,4.5;9,3;9]" .. + "list[current_player;main;0,7.74;9,1;]" .. + "label[4,0.5;"..F(minetest.colorize("#313131", S("Crafting"))) .. "]" .. + "list[current_player;craft;4,1;2,2]" .. + "list[current_player;craftpreview;7,1.5;1,1;]" .. + mcl_formspec.get_itemslot_bg(0, 4.5, 9, 3) .. + mcl_formspec.get_itemslot_bg(0, 7.74, 9, 1) .. + mcl_formspec.get_itemslot_bg(4, 1,2, 2) .. + mcl_formspec.get_itemslot_bg(7, 1.5, 1, 1) .. + + -- Crafting guide button + "image_button[4.5,3;1,1;craftguide_book.png;__mcl_craftguide;]" .. + "tooltip[__mcl_craftguide;"..F(S("Recipe book")) .. "]" .. + + -- Help button + "image_button[8,3;1,1;doc_button_icon_lores.png;__mcl_doc;]" .. + "tooltip[__mcl_doc;" .. F(S("Help")) .. "]" + + -- Skins button + if minetest.global_exists("mcl_skins") then + form = form .. + "image_button[3,3;1,1;mcl_skins_button.png;__mcl_skins;]" .. + "tooltip[__mcl_skins;" .. F(S("Select player skin")) .. "]" + end + + form = form .. + -- Achievements button + "image_button[7,3;1,1;mcl_achievements_button.png;__mcl_achievements;]" .. + "tooltip[__mcl_achievements;" .. F(S("Achievements")) .. "]" .. + + -- For shortcuts + "listring[current_player;main]" .. + "listring[current_player;armor]" .. + "listring[current_player;main]" .. + "listring[current_player;craft]" .. + "listring[current_player;main]" + player:set_inventory_formspec(form) end diff --git a/mods/ITEMS/mcl_maps/init.lua b/mods/ITEMS/mcl_maps/init.lua index 7b22ffef1..6fae7c13d 100644 --- a/mods/ITEMS/mcl_maps/init.lua +++ b/mods/ITEMS/mcl_maps/init.lua @@ -229,17 +229,40 @@ filled_wield_def.range = minetest.registered_items[""].range filled_wield_def.on_place = mcl_util.call_on_rightclick filled_wield_def._mcl_wieldview_item = "mcl_maps:filled_map" -for _, texture in pairs(mcl_skins.list) do - local def = table.copy(filled_wield_def) - def.tiles = {texture .. ".png"} - def.mesh = "mcl_meshhand.b3d" - def._mcl_hand_id = texture - minetest.register_node("mcl_maps:filled_map_" .. texture, def) +local mcl_skins_enabled = minetest.global_exists("mcl_skins") - local female_def = table.copy(def) - female_def.mesh = "mcl_meshhand_female.b3d" - female_def._mcl_hand_id = texture .. "_female" - minetest.register_node("mcl_maps:filled_map_" .. texture .. "_female", female_def) +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 + local bases = mcl_skins.base + local base_colors = mcl_skins.base_color + + -- Generate a node for every skin + for _, base in pairs(bases) do + for _, base_color in pairs(base_colors) do + local node_id = player_base_to_node_id(base, base_color, "male") + 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) + female._mcl_hand_id = node_id + female.mesh = "mcl_meshhand_female.b3d" + female.tiles = {texture} + minetest.register_node("mcl_maps:filled_map_" .. node_id, female) + end + end +else + filled_wield_def._mcl_hand_id = "hand" + filled_wield_def.mesh = "mcl_meshhand.b3d" + filled_wield_def.tiles = {"character.png"} + minetest.register_node("mcl_maps:filled_map_hand", filled_wield_def) end local old_add_item = minetest.add_item diff --git a/mods/PLAYER/mcl_meshhand/init.lua b/mods/PLAYER/mcl_meshhand/init.lua index 93f22c325..03335710f 100644 --- a/mods/PLAYER/mcl_meshhand/init.lua +++ b/mods/PLAYER/mcl_meshhand/init.lua @@ -1,76 +1,66 @@ -local has_mcl_skins = minetest.get_modpath("mcl_skins") ~= nil +local mcl_skins_enabled = minetest.global_exists("mcl_skins") -local def = minetest.registered_items[""] +-- This is a fake node that should never be placed in the world +local node_def = { + description = "", + use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, + visual_scale = 1, + wield_scale = {x=1,y=1,z=1}, + paramtype = "light", + drawtype = "mesh", + node_placement_prediction = "", + on_construct = function(pos) + local name = get_node(pos).name + local message = "[mcl_meshhand] Trying to construct " .. name .. " at " .. minetest.pos_to_string(pos) + minetest.log("error", message) + minetest.remove_node(pos) + end, + drop = "", + on_drop = function() return "" end, + groups = { dig_immediate = 3, not_in_creative_inventory = 1 }, + range = minetest.registered_items[""].range +} -local list --- mcl_skins is enabled -if has_mcl_skins == true then - list = mcl_skins.list -else - list = { "hand" } +local function player_base_to_node_id(base, colorspec, sex) + return base:gsub("%.", "") .. minetest.colorspec_to_colorstring(colorspec):gsub("#", "") .. sex end ---generate a node for every skin -for _,texture in pairs(list) do - -- This is a fake node that should never be placed in the world - minetest.register_node("mcl_meshhand:"..texture, { - description = "", - tiles = {texture..".png"}, - use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, - visual_scale = 1, - wield_scale = {x=1,y=1,z=1}, - paramtype = "light", - drawtype = "mesh", - mesh = "mcl_meshhand.b3d", - -- Prevent construction - node_placement_prediction = "", - on_construct = function(pos) - minetest.log("error", "[mcl_meshhand] Trying to construct mcl_meshhand:"..texture.." at "..minetest.pos_to_string(pos)) - minetest.remove_node(pos) - end, - drop = "", - on_drop = function() - return "" - end, - groups = { dig_immediate = 3, not_in_creative_inventory = 1 }, - range = def.range, - _mcl_hand_id = texture, - }) - - minetest.register_node("mcl_meshhand:"..texture.. "_female", { - description = "", - tiles = {texture..".png"}, - use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, - visual_scale = 1, - wield_scale = {x=1,y=1,z=1}, - paramtype = "light", - drawtype = "mesh", - mesh = "mcl_meshhand_female.b3d", - -- Prevent construction - node_placement_prediction = "", - on_construct = function(pos) - minetest.log("error", "[mcl_meshhand] Trying to construct mcl_meshhand:"..texture.." at "..minetest.pos_to_string(pos)) - minetest.remove_node(pos) - end, - drop = "", - on_drop = function() - return "" - end, - groups = { dig_immediate = 3, not_in_creative_inventory = 1 }, - range = def.range, - _mcl_hand_id = texture .. "_female", - }) -end - -if has_mcl_skins == true then - --change the player's hand to their skin - mcl_skins.register_on_set_skin(function(player, skin) - local meta = mcl_skins.meta[skin] - if meta.gender == "female" then - player:get_inventory():set_stack("hand", 1, "mcl_meshhand:"..skin.."_female") - else - player:get_inventory():set_stack("hand", 1, "mcl_meshhand:"..skin) +if mcl_skins_enabled then + local bases = mcl_skins.base + local base_colors = mcl_skins.base_color + + -- Generate a node for every skin + for _, base in pairs(bases) do + for _, base_color in pairs(base_colors) do + local node_id = player_base_to_node_id(base, base_color, "male") + 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) + female._mcl_hand_id = node_id + female.mesh = "mcl_meshhand_female.b3d" + female.tiles = {texture} + minetest.register_node("mcl_meshhand:" .. node_id, female) end + end +else + node_def._mcl_hand_id = "hand" + node_def.mesh = "mcl_meshhand.b3d" + node_def.tiles = {"character.png"} + minetest.register_node("mcl_meshhand:hand", node_def) +end + +if mcl_skins_enabled then + -- Change the player's hand to their skin + mcl_skins.register_on_set_skin(function(player) + local data = mcl_skins.players[player:get_player_name()] + 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) end) else minetest.register_on_joinplayer(function(player) diff --git a/mods/PLAYER/mcl_player/init.lua b/mods/PLAYER/mcl_player/init.lua index f717d4ba1..ccd5d5e0e 100644 --- a/mods/PLAYER/mcl_player/init.lua +++ b/mods/PLAYER/mcl_player/init.lua @@ -129,7 +129,7 @@ minetest.register_on_joinplayer(function(player) local name = player:get_player_name() mcl_player.player_attached[name] = false mcl_player.player_set_model(player, "character.b3d") - player_textures[name] = {"blank.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_fov(86.1) -- see >>> end) diff --git a/mods/PLAYER/mcl_skins/.gitignore b/mods/PLAYER/mcl_skins/.gitignore deleted file mode 100644 index 6edbd2834..000000000 --- a/mods/PLAYER/mcl_skins/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -!textures/mcl_skins_character_1.png -textures/mcl_skins_character_* -!meta/mcl_skins_character_1.txt -meta/mcl_skins_character_* \ No newline at end of file diff --git a/mods/PLAYER/mcl_skins/LICENSE.txt b/mods/PLAYER/mcl_skins/LICENSE.txt index fec6f6aa5..14ffbdee0 100644 --- a/mods/PLAYER/mcl_skins/LICENSE.txt +++ b/mods/PLAYER/mcl_skins/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 TenPlus1 +Copyright (c) 2022 MrRar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/mods/PLAYER/mcl_skins/README.md b/mods/PLAYER/mcl_skins/README.md index bbe5309ab..bc9924af9 100644 --- a/mods/PLAYER/mcl_skins/README.md +++ b/mods/PLAYER/mcl_skins/README.md @@ -1,13 +1,75 @@ -= Skins for MineClone 2 = +# mcl_skins -Simple mod to allow players to select a skin. -Use the chat command /setskin to change skin. +This mod allows advanced skin customization. +Use the /skin command to open the skin configuration screen. -Forked from Simple Skins by TenPlus1. -https://forum.minetest.net/viewtopic.php?id=9100 - -== License == +## License Code under MIT license -Origial authors: -- TenPlus1 -- Zeg9 +Author: MrRar + +See image_credits.txt for image licensing. + +## API + +### `mcl_skins.register_item(item)` +Register a skin item. `item` is a table with item properties listed below. + +### Item properties +`type` +Set the item type. Valid values are: "base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear" + +`texture` +Set to the image file that will be used. If this property is omitted "blank.png" is used. + +`mask` +Set the color mask texture. Coloring is only applied to non transparent areas of the texture. +Coloring only works for "base", "bottom, "top", and "hair". + +`preview_rotation` +A table containing properties x and y. x and y represent the x and y rotation of the item preview. + +`alex` +If set to true the item will be default for female character. + +`steve` +If set to true the item will be default for male character. + + +### `mcl_skins.show_formspec(player, active_tab, page_num)` +Show the skin configuration screen. +`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.register_on_set_skin(func)` +Register a function to be called whenever a player skin changes. +The function will be given a player ObjectRef as a parameter. + +### `mcl_skins.make_hand_texture(base, colorspec)` +Generate a texture string from a base texture and color. +This function is used by mods that want to have a first person hand textured like the player skin. + +### `mcl_skins.save(player)` +Save player skin. `player` is a player ObjectRef. + +### `mcl_skins.update_player_skin(player)` +Update a player based on skin data in mcl_skins.players. +`player` is a player ObjectRef. + +### `mcl_skins.base_color` +A table of ColorSpec integers that the player can select to color the base item. +These colors are separate from `mcl_skins.color` because some mods register two nodes per base color so the amount of base colors needs to be limited. + +### `mcl_skins.color` +A table of ColorSpec integers that the player can select to color colorable skin items. + +### `mcl_skins.players` +A table mapped by player name containing tables holding the player's selected skin items and colors. +Only stores skin information for logged in users. + +### mcl_skins.compile_skin(skin) +`skin` is a table with skin item properties. +Returns an image string. diff --git a/mods/PLAYER/mcl_skins/edit_skin.lua b/mods/PLAYER/mcl_skins/edit_skin.lua new file mode 100644 index 000000000..b650a645f --- /dev/null +++ b/mods/PLAYER/mcl_skins/edit_skin.lua @@ -0,0 +1,523 @@ +local S = minetest.get_translator("mcl_skins") +local color_to_string = minetest.colorspec_to_colorstring + +mcl_skins = { + item_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"}, + tab_names = {"template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"}, + 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"), + headwear = S("Headwears") + }, + steve = {}, -- Stores skin values for Steve skin + alex = {}, -- Stores skin values for Alex skin + 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 = { + 0xff613915, -- 1 Dark brown Steve hair, Alex bottom + 0xff97491b, -- 2 Medium brown + 0xffb17050, -- 3 Light brown + 0xffe2bc7b, -- 4 Beige + 0xff706662, -- 5 Gray + 0xff151515, -- 6 Black + 0xffc21c1c, -- 7 Red + 0xff178c32, -- 8 Green Alex top + 0xffae2ad3, -- 9 Plum + 0xffebe8e4, -- 10 White + 0xffe3dd26, -- 11 Yellow + 0xff449acc, -- 12 Light blue Steve top + 0xff124d87, -- 13 Dark blue Steve bottom + 0xfffc0eb3, -- 14 Pink + 0xffd0672a, -- 15 Orange Alex hair + }, + footwear = {}, + mouth = {}, + eye = {}, + bottom = {}, + top = {}, + hair = {}, + headwear = {}, + masks = {}, + preview_rotations = {}, + players = {} +} + +function mcl_skins.register_item(item) + assert(mcl_skins[item.type], "Skin item type " .. item.type .. " does not exist.") + local texture = item.texture or "blank.png" + if item.steve then + mcl_skins.steve[item.type] = texture + end + + if item.alex then + mcl_skins.alex[item.type] = texture + end + + table.insert(mcl_skins[item.type], texture) + mcl_skins.masks[texture] = item.mask + if item.preview_rotation then + mcl_skins.preview_rotations[texture] = item.preview_rotation + end +end + +function mcl_skins.save(player) + local name = player:get_player_name() + local skin = mcl_skins.players[name] + if not skin then return end + player:get_meta():set_string("mcl_skins:skin", minetest.serialize(skin)) +end + +minetest.register_chatcommand("skin", { + description = S("Open skin configuration screen."), + privs = {}, + func = function(name, param) mcl_skins.show_formspec(minetest.get_player_by_name(name)) end +}) + +function mcl_skins.make_hand_texture(base, colorspec) + local output = "" + if mcl_skins.masks[base] then + 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 + +function mcl_skins.compile_skin(skin) + local output = "" + for i, tab in pairs(mcl_skins.item_names) do + local texture = skin[tab] + if texture and texture ~= "blank.png" then + + if skin[tab .. "_color"] and mcl_skins.masks[texture] then + if #output > 0 then output = output .. "^" end + local color = color_to_string(skin[tab .. "_color"]) + output = output .. + "(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)" + end + if #output > 0 then output = output .. "^" end + output = output .. texture + end + end + return output +end + +function mcl_skins.update_player_skin(player) + if not player then + return + end + + local skin = mcl_skins.players[player:get_player_name()] + + 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" + mcl_player.player_set_model(player, model) + + mcl_inventory.update_inventory_formspec(player) + + for i=1, #mcl_skins.registered_on_set_skins do + mcl_skins.registered_on_set_skins[i](player) + end +end + +-- Load player skin on join +minetest.register_on_joinplayer(function(player) + local function table_get_random(t) + return t[math.random(#t)] + end + local name = player:get_player_name() + local skin = player:get_meta():get_string("mcl_skins:skin") + if skin then + skin = minetest.deserialize(skin) + end + if skin then + mcl_skins.players[name] = skin + else + if math.random() > 0.5 then + skin = table.copy(mcl_skins.steve) + else + skin = table.copy(mcl_skins.alex) + end + mcl_skins.players[name] = skin + end + mcl_skins.save(player) + mcl_skins.update_player_skin(player) +end) + +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + if name then + mcl_skins.players[name] = nil + end +end) + +mcl_skins.registered_on_set_skins = {} + +function mcl_skins.register_on_set_skin(func) + table.insert(mcl_skins.registered_on_set_skins, func) +end + +function mcl_skins.show_formspec(player, active_tab, page_num) + active_tab = active_tab or "template" + page_num = page_num or 1 + + local page_count + 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 + else + page_num = 1 + page_count = 1 + end + + local player_name = player:get_player_name() + local skin = mcl_skins.players[player_name] + local formspec = "formspec_version[3]size[13.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 .. + "button[0.3," .. y .. ";3,0.8;" .. tab .. ";" .. mcl_skins.tab_descriptions[tab] .. "]" + end + + local mesh = skin.slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d" + + formspec = formspec .. + "model[10,0.3;3,7;player_mesh;" .. mesh .. ";" .. + mcl_skins.compile_skin(skin) .. + ",blank.png,blank.png;0,180;false;true;0,0;0]" + + + if active_tab == "template" then + formspec = formspec .. + "model[4,2;2,3;player_mesh;mcl_armor_character.b3d;" .. + mcl_skins.compile_skin(mcl_skins.steve) .. + ",blank.png,blank.png;0,180;false;true;0,0;0]" .. + + "button[4,5.2;2,0.8;steve;" .. S("Select") .. "]" .. + + "model[6.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" .. + mcl_skins.compile_skin(mcl_skins.alex) .. + ",blank.png,blank.png;0,180;false;true;0,0;0]" .. + + "button[6.5,5.2;2,0.8;alex;" .. S("Select") .. "]" + + elseif mcl_skins[active_tab] then + formspec = formspec .. + "style_type[button;border=false;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] + 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 + + 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 = 3.5 + i % 4 * 1.6 + local y = 0.3 + math.floor(i / 4) * 1.6 + formspec = formspec .. + "model[" .. x .. "," .. y .. + ";1.5,1.5;" .. mesh .. ";" .. mesh .. ";" .. + preview .. + ";" .. rot_x .. "," .. rot_y .. ";false;false;0,0;0]" + + if skin[active_tab] == texture then + formspec = formspec .. + "style[" .. texture .. ";border=false;bgcolor=#00000000]" .. + "image_button[" .. x .. "," .. y .. + ";1.5,1.5;mcl_skins_select_overlay.png;" .. texture .. ";]" + else + formspec = formspec .. "button[" .. x .. "," .. y .. ";1.5,1.5;" .. texture .. ";]" + end + end + elseif active_tab == "arm" then + local thick_overlay = not skin.slim_arms and "^mcl_skins_select_overlay.png" or "" + local slim_overlay = skin.slim_arms and "^mcl_skins_select_overlay.png" or "" + formspec = formspec .. + "image_button[3.6,0.3;1,1;mcl_skins_thick_arms.png" .. thick_overlay ..";thick_arms;]" .. + "image_button[4.7,0.3;1,1;mcl_skins_slim_arms.png" .. slim_overlay ..";slim_arms;]" + 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 + local overlay = "" + if selected_color == colorspec then + overlay = "^mcl_skins_select_overlay.png" + end + + local color = color_to_string(colorspec) + i = i - 1 + local x = 3.6 + i % 6 * 0.9 + local y = 8 + math.floor(i / 6) * 0.9 + formspec = formspec .. + "image_button[" .. x .. "," .. y .. + ";0.8,0.8;blank.png^[noalpha^[colorize:" .. + color .. ":alpha" .. overlay .. ";" .. colorspec .. ";]" + end + + 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 .. + "container[9.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[3.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]" + end + + if page_num < page_count then + formspec = formspec .. + "image_button[8.8,6.7;1,1;mcl_skins_arrow.png;next_page;]" + end + + if page_count > 1 then + formspec = formspec .. + "label[6.3,7.2;" .. page_num .. " / " .. page_count .. "]" + end + + minetest.show_formspec(player_name, "mcl_skins:" .. active_tab .. "_" .. page_num, formspec) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if fields.__mcl_skins then + mcl_skins.show_formspec(player) + return false + end + + + if not formname:find("^mcl_skins:") then return false end + local _, _, active_tab, page_num = formname:find("^mcl_skins:(%a+)_(%d+)") + + 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) + + local player_name = player:get_player_name() + + -- Cancel formspec resend after scrollbar move + if mcl_skins.players[player_name].form_send_job then + mcl_skins.players[player_name].form_send_job:cancel() + end + + if fields.quit then + mcl_skins.save(player) + return true + end + + if fields.alex then + mcl_skins.players[player_name] = table.copy(mcl_skins.alex) + mcl_skins.update_player_skin(player) + mcl_skins.show_formspec(player, active_tab, page_num) + return true + elseif fields.steve then + mcl_skins.players[player_name] = table.copy(mcl_skins.steve) + mcl_skins.update_player_skin(player) + mcl_skins.show_formspec(player, active_tab, page_num) + return true + end + + for i, tab in pairs(mcl_skins.tab_names) do + if fields[tab] then + mcl_skins.show_formspec(player, tab, page_num) + return true + end + end + + local skin = mcl_skins.players[player_name] + 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) + return true + elseif fields.previous_page then + page_num = page_num - 1 + 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 + elseif fields.slim_arms then + skin.slim_arms = true + end + mcl_skins.update_player_skin(player) + 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 + 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 + + 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 + mcl_skins.players[player_name].form_send_job = minetest.after(0.2, function() + if player and player:is_player() then + skin[active_tab .. "_color"] = color + mcl_skins.update_player_skin(player) + mcl_skins.show_formspec(player, active_tab, page_num) + mcl_skins.players[player_name].form_send_job = nil + end + end) + return true + end + end + + local field + for f, value in pairs(fields) do + if value == "" then + field = f + break + end + end + + -- See if field is a texture + if field and mcl_skins[active_tab] then + for i, texture in pairs(mcl_skins[active_tab]) do + if texture == field then + skin[active_tab] = texture + mcl_skins.update_player_skin(player) + mcl_skins.show_formspec(player, active_tab, page_num) + return true + end + end + end + + -- 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) + mcl_skins.show_formspec(player, active_tab, page_num) + return true + end + end + + return true +end) + +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") + 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() + + for _, item in pairs(json) do + mcl_skins.register_item(item) + end + mcl_skins.steve.base_color = mcl_skins.base_color[1] + mcl_skins.steve.hair_color = mcl_skins.color[1] + mcl_skins.steve.top_color = mcl_skins.color[12] + mcl_skins.steve.bottom_color = mcl_skins.color[13] + mcl_skins.steve.slim_arms = false + + mcl_skins.alex.base_color = mcl_skins.base_color[1] + mcl_skins.alex.hair_color = mcl_skins.color[15] + mcl_skins.alex.top_color = mcl_skins.color[8] + mcl_skins.alex.bottom_color = mcl_skins.color[1] + mcl_skins.alex.slim_arms = true +end + +init() diff --git a/mods/PLAYER/mcl_skins/init.lua b/mods/PLAYER/mcl_skins/init.lua index 485e342b1..869e008d4 100644 --- a/mods/PLAYER/mcl_skins/init.lua +++ b/mods/PLAYER/mcl_skins/init.lua @@ -1,280 +1,4 @@ --- Skins for MineClone 2 - -local modname = minetest.get_current_modname() - -mcl_skins = { - skins = {}, list = {}, meta = {}, - modpath = minetest.get_modpath(modname), - skin_count = 0, -- counter of _custom_ skins (all skins except character.png) -} - -local S = minetest.get_translator(modname) -local has_mcl_inventory = minetest.get_modpath("mcl_inventory") - --- load skin list and metadata -local id, f, data, skin = 0 - -while true do - - if id == 0 then - skin = "character" - else - skin = "mcl_skins_character_" .. id - - -- Does skin file exist? - f = io.open(mcl_skins.modpath .. "/textures/" .. skin .. ".png") - - -- escape loop if not found - if not f then - break - end - f:close() - end - - mcl_skins.list[id] = skin - - 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(mcl_skins.modpath .. "/meta/" .. metafile) - - data = nil - if f then - data = minetest.deserialize("return {" .. f:read("*all") .. "}") - f:close() - end - - -- add metadata to list - mcl_skins.meta[skin] = { - name = data and data.name or "", - author = data and data.author or "", - gender = data and data.gender or "", - } - - if id > 0 then - mcl_skins.skin_count = mcl_skins.skin_count + 1 - end - id = id + 1 -end - -function mcl_skins.cycle_skin(player) - local skin_id = tonumber(player:get_meta():get_string("mcl_skins:skin_id")) - if not skin_id then - skin_id = 0 - end - skin_id = skin_id + 1 - if skin_id > mcl_skins.skin_count then - skin_id = 0 - end - mcl_skins.set_player_skin(player, skin_id) -end - -function mcl_skins.set_player_skin(player, skin_id) - if not player then - return false - end - local playername = player:get_player_name() - local skin - if skin_id == nil or type(skin_id) ~= "number" or skin_id < 0 or skin_id > mcl_skins.skin_count then - return false - elseif skin_id == 0 then - skin = "character" - mcl_player.player_set_model(player, "mcl_armor_character.b3d") - else - skin = "mcl_skins_character_" .. tostring(skin_id) - local meta = mcl_skins.meta[skin] - if meta.gender == "female" then - mcl_player.player_set_model(player, "mcl_armor_character_female.b3d") - else - mcl_player.player_set_model(player, "mcl_armor_character.b3d") - end - end - --local skin_file = skin .. ".png" - mcl_skins.skins[playername] = skin - player:get_meta():set_string("mcl_skins:skin_id", tostring(skin_id)) - mcl_skins.update_player_skin(player) - if has_mcl_inventory then - mcl_inventory.update_inventory_formspec(player) - end - for i=1, #mcl_skins.registered_on_set_skins do - mcl_skins.registered_on_set_skins[i](player, skin) - end - minetest.log("action", "[mcl_skins] Player skin for "..playername.." set to skin #"..skin_id) - return true -end - -function mcl_skins.update_player_skin(player) - if not player then - return - end - local playername = player:get_player_name() - mcl_player.player_set_skin(player, mcl_skins.skins[playername] .. ".png") -end - --- load player skin on join -minetest.register_on_joinplayer(function(player) - local name = player:get_player_name() - local skin_id = player:get_meta():get_string("mcl_skins:skin_id") - local set_skin - -- do we already have a skin in player attributes? - if skin_id and skin_id ~= "" then - set_skin = tonumber(skin_id) - -- otherwise use random skin if not set - end - if not set_skin then - set_skin = math.random(0, mcl_skins.skin_count) - end - local ok = mcl_skins.set_player_skin(player, set_skin) - if not ok then - set_skin = math.random(0, mcl_skins.skin_count) - minetest.log("warning", "[mcl_skins] Player skin for "..name.." not found, falling back to skin #"..set_skin) - mcl_skins.set_player_skin(player, set_skin) - end -end) - -mcl_skins.registered_on_set_skins = {} - -function mcl_skins.register_on_set_skin(func) - table.insert(mcl_skins.registered_on_set_skins, func) -end - --- command to set player skin (usually for custom skins) -minetest.register_chatcommand("setskin", { - params = S("[] []"), - description = S("Select player skin of yourself or another player"), - privs = {}, - func = function(name, param) - - if param == "" and name ~= "" then - mcl_skins.show_formspec(name) - return true - end - local playername, skin_id = string.match(param, "([^ ]+) (%d+)") - if not playername or not skin_id then - skin_id = string.match(param, "(%d+)") - if not skin_id then - return false, S("Insufficient or wrong parameters") - end - playername = name - end - skin_id = tonumber(skin_id) - - local player = minetest.get_player_by_name(playername) - - if not player then - return false, S("Player @1 not online!", playername) - end - if name ~= playername then - local privs = minetest.get_player_privs(name) - if not privs.server then - return false, S("You need the “server” privilege to change the skin of other players!") - end - end - - local ok = mcl_skins.set_player_skin(player, skin_id) - if not ok then - return false, S("Invalid skin number! Valid numbers: 0 to @1", mcl_skins.skin_count) - end - local skinfile = "#"..skin_id - - local meta = mcl_skins.meta[mcl_skins.skins[playername]] - local your_msg - if not meta.name or meta.name == "" then - your_msg = S("Your skin has been set to: @1", skinfile) - else - your_msg = S("Your skin has been set to: @1 (@2)", meta.name, skinfile) - end - if name == playername then - return true, your_msg - else - minetest.chat_send_player(playername, your_msg) - return true, S("Skin of @1 set to: @2 (@3)", playername, meta.name, skinfile) - end - - end, -}) - -minetest.register_on_player_receive_fields(function(player, formname, fields) - if fields.__mcl_skins then - if mcl_skins.skin_count <= 6 then - -- Change skin immediately if there are not many skins - mcl_skins.cycle_skin(player) - if player:get_attach() then - mcl_player.player_set_animation(player, "sit") - end - else - -- Show skin selection formspec otherwise - mcl_skins.show_formspec(player:get_player_name()) - end - end -end) - -function mcl_skins.show_formspec(playername) - local formspec = "size[7,8.5]" - - formspec = formspec .. "label[2,2;" .. minetest.formspec_escape(minetest.colorize("#383838", S("Select player skin:"))) .. "]" - .. "textlist[0,2.5;6.8,6;skins_set;" - - local meta - local selected = 1 - - for i = 0, mcl_skins.skin_count do - - local label = S("@1 (@2)", mcl_skins.meta[mcl_skins.list[i]].name, "#"..i) - - formspec = formspec .. minetest.formspec_escape(label) - - if mcl_skins.skins[playername] == mcl_skins.list[i] then - selected = i + 1 - meta = mcl_skins.meta[mcl_skins.list[i]] - end - - if i < #mcl_skins.list then - formspec = formspec .."," - end - end - - formspec = formspec .. ";" .. selected .. ";false]" - - local player = minetest.get_player_by_name(playername) - if player then - --maybe the function could accept both player object and player name? - formspec = formspec .. mcl_player.get_player_formspec_model(player, 0, 0, 1.35, 2.7, "mcl_skins:skin_select") - end - - if meta then - if meta.name and meta.name ~= "" then - formspec = formspec .. "label[2,0.5;" .. minetest.formspec_escape(minetest.colorize("#383838", S("Name: @1", meta.name))) .. "]" - end - end - - minetest.show_formspec(playername, "mcl_skins:skin_select", formspec) -end - -minetest.register_on_player_receive_fields(function(player, formname, fields) - - if formname == "mcl_skins:skin_select" then - - local name = player:get_player_name() - - local event = minetest.explode_textlist_event(fields["skins_set"]) - - if event.type == "CHG" or event.type == "DCL" then - - local skin_id = math.min(event.index - 1, mcl_skins.skin_count) - if not mcl_skins.list[skin_id] then - return -- Do not update wrong skin number - end - - mcl_skins.set_player_skin(player, skin_id) - mcl_skins.show_formspec(name) - end - end -end) - -minetest.log("action", "[mcl_skins] Mod initialized with "..mcl_skins.skin_count.." custom skin(s)") +local mod_path = minetest.get_modpath(minetest.get_current_modname()) + +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 diff --git a/mods/PLAYER/mcl_skins/list.json b/mods/PLAYER/mcl_skins/list.json new file mode 100644 index 000000000..e31c38066 --- /dev/null +++ b/mods/PLAYER/mcl_skins/list.json @@ -0,0 +1,259 @@ +[ + { + "type": "footwear", + "texture": "mcl_skins_footwear_1.png", + "steve": true, + "alex": true + }, + { + "type": "footwear", + "texture": "mcl_skins_footwear_2.png" + }, + { + "type": "footwear", + "texture": "mcl_skins_footwear_3.png" + }, + { + "type": "footwear" + }, + { + "type": "eye", + "texture": "mcl_skins_eye_1.png" + }, + { + "type": "eye", + "texture": "mcl_skins_eye_2.png" + }, + { + "type": "eye", + "texture": "mcl_skins_eye_3.png" + }, + { + "type": "eye", + "texture": "mcl_skins_eye_4.png" + }, + { + "type": "eye", + "texture": "mcl_skins_eye_5.png", + "steve": true, + "alex": true + }, + { + "type": "eye", + "texture": "mcl_skins_eye_6.png" + }, + { + "type": "eye", + "texture": "mcl_skins_eye_7.png" + }, + { + "type": "mouth", + "texture": "mcl_skins_mouth_1.png", + "steve": true + }, + { + "type": "mouth", + "texture": "mcl_skins_mouth_2.png" + }, + { + "type": "mouth", + "texture": "mcl_skins_mouth_3.png" + }, + { + "type": "mouth", + "texture": "mcl_skins_mouth_4.png" + }, + { + "type": "mouth", + "texture": "mcl_skins_mouth_5.png" + }, + { + "type": "mouth", + "texture": "mcl_skins_mouth_6.png" + }, + { + "type": "mouth", + "texture": "mcl_skins_mouth_7.png", + "alex": true + }, + { + "type": "mouth" + }, + { + "type": "hair", + "texture": "mcl_skins_hair_1.png", + "mask": "mcl_skins_hair_1_mask.png" + }, + { + "type": "hair", + "texture": "mcl_skins_hair_2.png", + "mask": "mcl_skins_hair_2_mask.png" + }, + { + "type": "hair", + "texture": "mcl_skins_hair_3.png", + "mask": "mcl_skins_hair_3_mask.png" + }, + { + "type": "hair", + "texture": "mcl_skins_hair_4.png", + "mask": "mcl_skins_hair_4_mask.png" + }, + { + "type": "hair", + "texture": "mcl_skins_hair_5.png", + "mask": "mcl_skins_hair_5_mask.png" + }, + { + "type": "hair", + "texture": "mcl_skins_hair_6.png", + "mask": "mcl_skins_hair_6_mask.png" + }, + { + "type": "hair", + "texture": "mcl_skins_hair_7.png", + "mask": "mcl_skins_hair_7_mask.png" + }, + { + "type": "hair", + "texture": "mcl_skins_hair_8.png", + "mask": "mcl_skins_hair_8_mask.png" + }, + { + "type": "hair", + "texture": "mcl_skins_hair_9.png", + "mask": "mcl_skins_hair_9_mask.png" + }, + { + "type": "hair", + "texture": "mcl_skins_hair_10.png", + "mask": "mcl_skins_hair_10_mask.png", + "steve": true + }, + { + "type": "hair", + "texture": "mcl_skins_hair_11.png", + "mask": "mcl_skins_hair_11_mask.png", + "alex": true + }, + { + "type": "hair" + }, + { + "type": "headwear", + "texture": "mcl_skins_headwear_1.png" + }, + { + "type": "headwear", + "texture": "mcl_skins_headwear_2.png" + }, + { + "type": "headwear", + "texture": "mcl_skins_headwear_3.png" + }, + { + "type": "headwear", + "texture": "mcl_skins_headwear_4.png" + }, + { + "type": "headwear", + "texture": "mcl_skins_headwear_5.png" + }, + { + "type": "headwear", + "texture": "mcl_skins_headwear_6.png", + "preview_rotation": { + "x": -10, + "y": 200 + } + }, + { + "type": "headwear", + "texture": "mcl_skins_headwear_7.png" + }, + { + "type": "headwear", + "steve": true + }, + { + "type": "bottom", + "texture": "mcl_skins_bottom_1.png", + "mask": "mcl_skins_bottom_1_mask.png" + }, + { + "type": "bottom", + "texture": "mcl_skins_bottom_2.png", + "mask": "mcl_skins_bottom_2_mask.png" + }, + { + "type": "bottom", + "texture": "mcl_skins_bottom_3.png", + "mask": "mcl_skins_bottom_3_mask.png" + }, + { + "type": "bottom", + "texture": "mcl_skins_bottom_4.png", + "mask": "mcl_skins_bottom_4_mask.png", + "steve": true, + "alex": true + }, + { + "type": "top", + "texture": "mcl_skins_top_1.png", + "mask": "mcl_skins_top_1_mask.png" + }, + { + "type": "top", + "texture": "mcl_skins_top_2.png", + "mask": "mcl_skins_top_2_mask.png" + }, + { + "type": "top", + "texture": "mcl_skins_top_3.png", + "mask": "mcl_skins_top_3_mask.png" + }, + { + "type": "top", + "texture": "mcl_skins_top_4.png", + "mask": "mcl_skins_top_4_mask.png" + }, + { + "type": "top", + "texture": "mcl_skins_top_5.png", + "mask": "mcl_skins_top_5_mask.png" + }, + { + "type": "top", + "texture": "mcl_skins_top_6.png", + "mask": "mcl_skins_top_6_mask.png" + }, + { + "type": "top", + "texture": "mcl_skins_top_7.png", + "mask": "mcl_skins_top_7_mask.png" + }, + { + "type": "top", + "texture": "mcl_skins_top_8.png", + "mask": "mcl_skins_top_8_mask.png" + }, + { + "type": "top", + "texture": "mcl_skins_top_9.png", + "mask": "mcl_skins_top_9_mask.png", + "alex": true + }, + { + "type": "top", + "texture": "mcl_skins_top_10.png", + "mask": "mcl_skins_top_10_mask.png", + "steve": true + }, + { + "type": "base", + "texture": "mcl_skins_base_1.png", + "mask": "mcl_skins_base_1_mask.png", + "steve": true, + "alex": true + } +] diff --git a/mods/PLAYER/mcl_skins/locale/mcl_skins.de.tr b/mods/PLAYER/mcl_skins/locale/mcl_skins.de.tr deleted file mode 100644 index 8f9b488db..000000000 --- a/mods/PLAYER/mcl_skins/locale/mcl_skins.de.tr +++ /dev/null @@ -1,13 +0,0 @@ -# textdomain: mcl_skins -[] []=[] [] -Select player skin of yourself or another player=Spieleraussehen von Ihnen oder einem anderen Spieler auswählen -Insufficient or wrong parameters=Unzureichende oder falsche Parameter -Player @1 not online!=Spieler @1 ist nicht online! -You need the “server” privilege to change the skin of other players!=Sie brauchen das „server“-Privileg, um das Aussehen anderer Spieler zu ändern! -Invalid skin number! Valid numbers: 0 to @1=Ungültige Aussehens-Nummer! Gültige Nummern: 0 bis @1 -Your skin has been set to: @1=Ihr Aussehen wurde geändert auf: @1 -Your skin has been set to: @1 (@2)=Ihr Aussehen wurde geändert auf: @1 (@2) -Skin of @1 set to: @2 (@3)=Aussehen von @1 gesetzt auf: @2 (@3) -Select player skin:=Spieleraussehen wählen: -@1 (@2)=@1 (@2) -Name: @1=Name: @1 diff --git a/mods/PLAYER/mcl_skins/locale/mcl_skins.es.tr b/mods/PLAYER/mcl_skins/locale/mcl_skins.es.tr deleted file mode 100644 index dcd5c8438..000000000 --- a/mods/PLAYER/mcl_skins/locale/mcl_skins.es.tr +++ /dev/null @@ -1,13 +0,0 @@ -# textdomain: mcl_skins -[] []=[] [] -Select player skin of yourself or another player=Selecciona el skin tuyo o de otro jugador -Insufficient or wrong parameters=Parámetros insuficientes o incorrectos -Player @1 not online!=¡El jugador @1 no está en línea! -You need the “server” privilege to change the skin of other players!=¡Necesitas el privilegio de "servidor" para cambiar el aspecto de otros jugadores! -Invalid skin number! Valid numbers: 0 to @1=¡Número de piel no válido! Números válidos: 0 a @1 -Your skin has been set to: @1=Su skin se ha configurado a: @1 -Your skin has been set to: @1 (@2)=Su skin se ha configurado a: @1 (@2) -Skin of @1 set to: @2 (@3)=El skin de @1 se ha configurado a: @2 (@3) -Select player skin:=Selecciona el skin del jugador: -@1 (@2)=@1 (@2) -Name: @1=Nombre: @1 diff --git a/mods/PLAYER/mcl_skins/locale/mcl_skins.fr.tr b/mods/PLAYER/mcl_skins/locale/mcl_skins.fr.tr index 146c6be5f..db937b040 100644 --- a/mods/PLAYER/mcl_skins/locale/mcl_skins.fr.tr +++ b/mods/PLAYER/mcl_skins/locale/mcl_skins.fr.tr @@ -1,14 +1,13 @@ # textdomain: mcl_skins -[] []=[] [] -Select player skin of yourself or another player=Sélectionner une apparence pour vous même ou un autre joueur -Insufficient or wrong parameters=Paramètres insuffisants ou incorrects -Player @1 not online!=Le joueur @1 n'est pas en ligne! -You need the “server” privilege to change the skin of other players!=Vous avez besoin du privilège “server” pour changer l'apparence des autres joueurs! -Invalid skin number! Valid numbers: 0 to @1=Numéro d'apparence incorrect! Numéros valides : 0 à @1 -Your skin has been set to: @1=Votre apparence a été définie à: @1 -Your skin has been set to: @1 (@2)=Votre apparence a été définie à: @1 (@2) -Skin of @1 set to: @2 (@3)=Apparence of @1 set to: @2 (@3)= -Select player skin:=Sélectionner l'apparence du joueur : -@1 (@2)=@1 (@2) -Name: @1=Nom : @ - +Templates=Modèles +Arm size=Taille des bras +Bases=Teint +Footwears=Chaussures +Eyes=Yeux +Mouths=Bouches +Bottoms=Bas +Tops=Haut +Hairs=Cheveux +Headwears=Coiffe +Open skin configuration screen.=Ouvrir l'écran de configuration du costume. +Select=Sélectionner \ No newline at end of file diff --git a/mods/PLAYER/mcl_skins/locale/mcl_skins.ms.tr b/mods/PLAYER/mcl_skins/locale/mcl_skins.ms.tr deleted file mode 100644 index 58946f605..000000000 --- a/mods/PLAYER/mcl_skins/locale/mcl_skins.ms.tr +++ /dev/null @@ -1,16 +0,0 @@ -# textdomain: mcl_skins -# UNFINISHED translation! -# TODO: Remove the # sign from the translations below and add the missing translations. - -[] []= -Select player skin of yourself or another player= -Insufficient or wrong parameters= -Player @1 not online!= -You need the “server” privilege to change the skin of other players!= -Invalid skin number! Valid numbers: 0 to @1= -Your skin has been set to: @1= -Your skin has been set to: @1 (@2)= -Skin of @1 set to: @2 (@3)= -Select player skin:=Pilih Kulit Pemain: -@1 (@2)= -Name: @1=Nama: @1 diff --git a/mods/PLAYER/mcl_skins/locale/mcl_skins.pl.tr b/mods/PLAYER/mcl_skins/locale/mcl_skins.pl.tr deleted file mode 100644 index 9b07cea2c..000000000 --- a/mods/PLAYER/mcl_skins/locale/mcl_skins.pl.tr +++ /dev/null @@ -1,13 +0,0 @@ -# textdomain: mcl_skins -[] []=[] [] -Select player skin of yourself or another player=Wybierz skin gracza dla siebie lub innego gracza -Insufficient or wrong parameters=Niewystarczające lub złe parametry -Player @1 not online!=Gracz @1 nie jest online! -You need the “server” privilege to change the skin of other players!=Potrzebujesz uprawnienia "serwer", aby zmieniać skiny innych graczy! -Invalid skin number! Valid numbers: 0 to @1=Niepoprawny numer skina! Poprawne numery: od 0 do @1 -Your skin has been set to: @1=Twój skin został ustawiony na: @1 -Your skin has been set to: @1 (@2)=Twój skin został ustawiony na: @1 (@2) -Skin of @1 set to: @2 (@3)=Skin gracza @1 ustawiony na @2 (@3) -Select player skin:=Wybierz skin gracza: -@1 (@2)=@1 (@2) -Name: @1=Nazwa: @1 diff --git a/mods/PLAYER/mcl_skins/locale/mcl_skins.ru.tr b/mods/PLAYER/mcl_skins/locale/mcl_skins.ru.tr deleted file mode 100644 index 64eab0e3f..000000000 --- a/mods/PLAYER/mcl_skins/locale/mcl_skins.ru.tr +++ /dev/null @@ -1,13 +0,0 @@ -# textdomain: mcl_skins -[] []=[<игрок>] [<номер скина>] -Select player skin of yourself or another player=Выберите скин для себя или для другого игрока -Insufficient or wrong parameters=Недопустимые или неправильные параметры -Player @1 not online!=Игрок @1 не в сети! -You need the “server” privilege to change the skin of other players!=Для смены скинов другим игрокам у вас должна быть привилегия “server”! -Invalid skin number! Valid numbers: 0 to @1=Недопустимый номер скина! Правильные номера: от 0 до @1 -Your skin has been set to: @1=Ваш скин выбран: @1 -Your skin has been set to: @1 (@2)=Ваш скин установлен: @1 (@2) -Skin of @1 set to: @2 (@3)=Скин игрока @1 установлен: @2 (@3) -Select player skin:=Выбор скина игрока: -@1 (@2)=@1 (@2) -Name: @1=Имя: @1 diff --git a/mods/PLAYER/mcl_skins/locale/mcl_skins.zh_TW.tr b/mods/PLAYER/mcl_skins/locale/mcl_skins.zh_TW.tr deleted file mode 100644 index 1347800ee..000000000 --- a/mods/PLAYER/mcl_skins/locale/mcl_skins.zh_TW.tr +++ /dev/null @@ -1,13 +0,0 @@ -# textdomain: mcl_skins -[] []=[<玩家名字>] [<皮膚篇號>] -Select player skin of yourself or another player=替自己或其他玩家選擇皮膚 -Insufficient or wrong parameters=無效或錯誤參數 -Player @1 not online!=玩家 @1 不在線! -You need the “server” privilege to change the skin of other players!=你需要「server」權限來替換其他玩家的皮膚! -Invalid skin number! Valid numbers: 0 to @1=無效皮膚篇號!有效篇號:0至@1 -Your skin has been set to: @1=你的皮膚已換成:@1 -Your skin has been set to: @1 (@2)=你的皮膚已換成:@1(@2) -Skin of @1 set to: @2 (@3)=@1的皮膚已換成:@1 -Select player skin:=選擇玩家皮膚: -@1 (@2)=@1(@2) -Name: @1=名稱:@1 diff --git a/mods/PLAYER/mcl_skins/locale/template.txt b/mods/PLAYER/mcl_skins/locale/template.txt index c683fa4e4..1facf03d5 100644 --- a/mods/PLAYER/mcl_skins/locale/template.txt +++ b/mods/PLAYER/mcl_skins/locale/template.txt @@ -1,13 +1,13 @@ # textdomain: mcl_skins -[] []= -Select player skin of yourself or another player= -Insufficient or wrong parameters= -Player @1 not online!= -You need the “server” privilege to change the skin of other players!= -Invalid skin number! Valid numbers: 0 to @1= -Your skin has been set to: @1= -Your skin has been set to: @1 (@2)= -Skin of @1 set to: @2 (@3)= -Select player skin:= -@1 (@2)= -Name: @1= +Templates= +Arm size= +Bases= +Footwears= +Eyes= +Mouths= +Bottoms= +Tops= +Hairs= +Headwears= +Open skin configuration screen.= +Select= diff --git a/mods/PLAYER/mcl_skins/media_credits.txt b/mods/PLAYER/mcl_skins/media_credits.txt new file mode 100644 index 000000000..b81058356 --- /dev/null +++ b/mods/PLAYER/mcl_skins/media_credits.txt @@ -0,0 +1,115 @@ +mcl_skins_base_1.png +mcl_skins_button.png +mcl_skins_footwear_3.png +mcl_skins_headgear_1.png +mcl_skins_headgear_3.png +mcl_skins_headgear_4.png +mcl_skins_headgear_5.png +mcl_skins_mouth_2.png +mcl_skins_mouth_3.png +mcl_skins_mouth_4.png +mcl_skins_mouth_5.png +mcl_skins_select_overlay.png +mcl_skins_slim_arms.png +mcl_skins_thick_arms.png +mcl_skins_top_2.png +mcl_skins_top_5.png +mcl_skins_eye_5.png +mcl_skins_hair_8.png +mcl_skins_top_6.png +mcl_skins_bottom_3.png +mcl_skins_eye_7.png +mcl_skins_mouth_7.png +Original work by MrRar +License: CC BY-SA 4.0 + +mcl_skins_top_1.png +mcl_skins_mouth_1.png +mcl_skins_hair_1.png +mcl_skins_hair_2.png +mcl_skins_eye_1.png +mcl_skins_eye_2.png +mcl_skins_footwear_1.png +mcl_skins_headgear_2.png +mcl_skins_mouth_1.png +mcl_skins_top_1.png +mcl_skins_mouth_2.png +Name: Pixel Perfection resource pack for Minecraft 1.11 +Author: XSSheep. Adapted for mcl_skins by MrRar. +License: CC BY-SA 4.0 +Source: https://www.planetminecraft.com/texture_pack/131pixel-perfection/ + +mcl_skins_hair_3.png +mcl_skins_eye_3.png +mcl_skins_footwear_2.png +Name: the 10the doctor +Author: lovehart. Adapted for mcl_skins by MrRar. +License: CC BY-SA 3.0 +Source: http://minetest.fensta.bplaced.net/#!page:1,filtertype:Id,filter:367 + +mcl_skins_hair_4.png +Blonde Girl +Author: Rin. Adapted for mcl_skins by MrRar. +License: CC BY-SA 3.0 +Source: http://minetest.fensta.bplaced.net/#id=918 + +mcl_skins_hair_5.png +Name: hobbit from lottmob +Author: lovehart. Adapted for mcl_skins by MrRar. +License: CC BY-SA 3.0 +Source: http://minetest.fensta.bplaced.net/#id=336 + +mcl_skins_top_4.png +Name: Oliver_MV +Author: hansuke123. Adapted for mcl_skins by MrRar. +License: CC BY-SA 3.0 +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 +Name: lisa +Author: hansuke123 +License: CC BY-SA 3.0 +Source: http://minetest.fensta.bplaced.net/#!page:1,filtertype:Id,filter:88 + +mcl_skins_headwear_7.png +Name: Ryu +Author: Ginsu23. Adapted for mcl_skins by MrRar. +License: CC BY-SA 3.0 +Source: http://minetest.fensta.bplaced.net/#id=464 + +mcl_skins_top_8.png +Name: Hoodie Enderman +Author: Kpenguin. Adapted for mcl_skins by MrRar. +License: CC BY-SA 3.0 +Source: http://minetest.fensta.bplaced.net/#id=962 + +mcl_skins_hair_9.png +Name: Trader 1 +Author: TenPlus1. Adapted for mcl_skins by MrRar. +License: CC BY-SA 3.0 +Source: http://minetest.fensta.bplaced.net/#id=1258 + +mcl_skins_bottom_4.png +mcl_skins_top_9.png +mcl_skins_top_10.png +mcl_skins_hair_10.png +mcl_skins_hair_11.png +Name: Pixel Perfection Legacy 1.19 +Author: Nova_Wostra. Adapted for mcl_skins by MrRar. +License: CC BY-SA 4.0 +Source: https://www.planetminecraft.com/texture-pack/pixel-perfection-chorus-edit/ + +mcl_skins_bottom.obj +mcl_skins_head.obj +mcl_skins_top.obj +Name: character.blend in player_api mod from Minetest Game +Author: celeron55, MirceaKitsune, Jordach, kilbith, sofar, xunto, Rogier-5, TeTpaAka, Desour, stujones11, An0n3m0us. Adapted for mcl_skins by MrRar. +License: CC BY-SA 3.0 +Source: https://github.com/minetest/minetest_game diff --git a/mods/PLAYER/mcl_skins/meta/mcl_skins_character.txt b/mods/PLAYER/mcl_skins/meta/mcl_skins_character.txt deleted file mode 100644 index c31bd7168..000000000 --- a/mods/PLAYER/mcl_skins/meta/mcl_skins_character.txt +++ /dev/null @@ -1,3 +0,0 @@ -name = "Steve", -author = "%TEXTURE_PACK_AUTHOR%", -gender = "male", diff --git a/mods/PLAYER/mcl_skins/meta/mcl_skins_character_1.txt b/mods/PLAYER/mcl_skins/meta/mcl_skins_character_1.txt deleted file mode 100644 index e6c90dc0f..000000000 --- a/mods/PLAYER/mcl_skins/meta/mcl_skins_character_1.txt +++ /dev/null @@ -1,3 +0,0 @@ -name = "Alex", -author = "%TEXTURE_PACK_AUTHOR%", -gender = "female", diff --git a/mods/PLAYER/mcl_skins/mod.conf b/mods/PLAYER/mcl_skins/mod.conf index 657d3cc0e..f631b76dc 100644 --- a/mods/PLAYER/mcl_skins/mod.conf +++ b/mods/PLAYER/mcl_skins/mod.conf @@ -1,5 +1,4 @@ name = mcl_skins -author = TenPlus1 -description = Mod that allows players to set their individual skins. -depends = mcl_player -optional_depends = mcl_inventory, intllib +author = MrRar +description = Advanced player skin customization. +depends = mcl_player,mcl_inventory diff --git a/mods/PLAYER/mcl_skins/models/mcl_skins_bottom.obj b/mods/PLAYER/mcl_skins/models/mcl_skins_bottom.obj new file mode 100644 index 000000000..bc12779af --- /dev/null +++ b/mods/PLAYER/mcl_skins/models/mcl_skins_bottom.obj @@ -0,0 +1,108 @@ +# Blender v2.93.5 OBJ File: '' +# www.blender.org +mtllib bottom.mtl +o bottom +v -2.100000 4.358421 1.050001 +v -2.100000 1.648314 1.049999 +v 2.100000 1.648314 1.049999 +v 2.100000 4.358421 1.050001 +v -2.100000 1.648314 -1.050001 +v -2.100000 4.358421 -1.049998 +v 2.100000 1.648314 -1.050001 +v 2.100000 4.358421 -1.049998 +v 0.000000 1.648314 -1.050001 +v 0.000000 -4.651686 -1.050003 +v 0.000000 -4.651686 1.049997 +v 0.000000 1.648314 1.049999 +v 0.000000 -4.651686 -1.050003 +v 0.000000 -4.651686 1.049997 +v -2.100000 -4.651685 1.049997 +v -2.100000 -4.651685 -1.050003 +v -2.100000 1.648315 1.049999 +v -2.100000 1.648315 -1.050001 +v 0.000000 1.648314 1.049999 +v 2.100000 1.648315 -1.050001 +v 2.100000 -4.651685 -1.050003 +v 0.000000 1.648314 -1.050001 +v 2.100000 -4.651685 1.049997 +v 2.100000 1.648315 1.049999 +vt 0.500000 0.161316 +vt 0.500000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.161316 +vt 0.437500 0.000000 +vt 0.437500 0.161316 +vt 0.312500 0.000000 +vt 0.312500 0.161316 +vt 0.562500 0.375000 +vt 0.562500 0.500000 +vt 0.437500 0.500000 +vt 0.437500 0.375000 +vt 0.125000 0.375000 +vt 0.125000 0.000000 +vt 0.187500 0.000000 +vt 0.187500 0.375000 +vt 0.187500 0.375000 +vt 0.187500 0.500000 +vt 0.125000 0.500000 +vt 0.125000 0.375000 +vt 0.000000 0.375000 +vt 0.062500 0.375000 +vt 0.062500 0.000000 +vt 0.000000 0.000000 +vt 0.187500 0.375000 +vt 0.250000 0.375000 +vt 0.250000 0.000000 +vt 0.187500 0.000000 +vt 0.062500 0.375000 +vt 0.062500 0.000000 +vt 0.125000 0.375000 +vt 0.125000 0.000000 +vt 0.250000 0.000000 +vt 0.250000 0.375000 +vt 0.000000 0.375000 +vt 0.000000 0.000000 +vt 0.250000 0.161316 +vt 0.250000 0.000000 +vt 0.125000 0.375000 +vt 0.125000 0.500000 +vt 0.062500 0.500000 +vt 0.062500 0.375000 +vt 0.187500 0.375000 +vt 0.125000 0.375000 +vt 0.125000 0.500000 +vt 0.187500 0.500000 +vt 0.125000 0.375000 +vt 0.062500 0.375000 +vt 0.062500 0.500000 +vt 0.125000 0.500000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vn 0.0000 -0.0000 1.0000 +vn -1.0000 -0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 -1.0000 -0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 1.0000 0.0000 +usemtl Character +s 1 +f 1/1/1 2/2/1 3/3/1 4/4/1 +f 5/5/2 2/2/2 1/1/2 6/6/2 +f 7/7/3 5/5/3 6/6/3 8/8/3 +f 7/9/4 3/10/4 2/11/4 5/12/4 +f 9/13/2 10/14/2 11/15/2 12/16/2 +f 13/17/4 14/18/4 15/19/4 16/20/4 +f 17/21/2 18/22/2 16/23/2 15/24/2 +f 19/25/1 17/26/1 15/27/1 14/28/1 +f 20/29/3 21/30/3 10/14/3 9/13/3 +f 18/22/3 22/31/3 13/32/3 16/23/3 +f 12/16/1 11/15/1 23/33/1 24/34/1 +f 22/31/5 19/25/5 14/28/5 13/32/5 +f 24/35/5 23/36/5 21/30/5 20/29/5 +f 4/37/5 3/38/5 7/7/5 8/8/5 +f 18/39/6 17/40/6 19/41/6 22/42/6 +f 10/43/4 21/44/4 23/45/4 11/46/4 +f 20/47/6 9/48/6 12/49/6 24/50/6 +f 4/51/6 8/52/6 6/53/6 1/54/6 diff --git a/mods/PLAYER/mcl_skins/models/mcl_skins_head.obj b/mods/PLAYER/mcl_skins/models/mcl_skins_head.obj new file mode 100644 index 000000000..226a0d9bb --- /dev/null +++ b/mods/PLAYER/mcl_skins/models/mcl_skins_head.obj @@ -0,0 +1,72 @@ +# Blender v2.93.5 OBJ File: '' +# www.blender.org +mtllib head.mtl +o head +v -2.100000 -2.100004 2.099999 +v 2.100000 2.099997 -2.100001 +v 2.100000 2.099997 2.099999 +v 2.300000 -2.300003 -2.300001 +v 2.300000 2.299997 2.299999 +v 2.100000 -2.100004 2.099999 +v 2.100000 -2.100004 -2.100001 +v -2.100000 2.099997 2.099999 +v -2.100000 2.099997 -2.100001 +v -2.100000 -2.100004 -2.100001 +v 2.300000 2.299997 -2.300001 +v 2.300000 -2.300003 2.299999 +v -2.300000 2.299997 2.299999 +v -2.300000 -2.300003 2.299999 +v -2.300000 2.299997 -2.300001 +v -2.300000 -2.300003 -2.300001 +vt 0.500000 0.750000 +vt 0.375000 0.750000 +vt 0.375000 0.500000 +vt 0.500000 0.500000 +vt 0.250000 0.750000 +vt 0.250000 0.500000 +vt 0.125000 0.750000 +vt 0.125000 0.500000 +vt 0.375000 0.750000 +vt 0.375000 1.000000 +vt 0.250000 1.000000 +vt 0.250000 0.750000 +vt 0.250000 1.000000 +vt 0.125000 1.000000 +vt 0.000000 0.750000 +vt 0.000000 0.500000 +vt 1.000000 0.750000 +vt 0.875000 0.750000 +vt 0.875000 0.500000 +vt 1.000000 0.500000 +vt 0.750000 0.750000 +vt 0.750000 0.500000 +vt 0.625000 0.750000 +vt 0.625000 0.500000 +vt 0.875000 0.750000 +vt 0.875000 1.000000 +vt 0.750000 1.000000 +vt 0.750000 0.750000 +vt 0.750000 1.000000 +vt 0.625000 1.000000 +vt 0.500000 0.750000 +vt 0.500000 0.500000 +vn 0.0000 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 -1.0000 0.0000 +vn 0.0000 1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +usemtl Character +s off +f 3/1/1 8/2/1 1/3/1 6/4/1 +f 8/2/2 9/5/2 10/6/2 1/3/2 +f 9/5/3 2/7/3 7/8/3 10/6/3 +f 7/9/4 6/10/4 1/11/4 10/12/4 +f 9/5/5 8/13/5 3/14/5 2/7/5 +f 3/15/6 6/16/6 7/8/6 2/7/6 +f 5/17/1 13/18/1 14/19/1 12/20/1 +f 13/18/2 15/21/2 16/22/2 14/19/2 +f 15/21/3 11/23/3 4/24/3 16/22/3 +f 4/25/4 12/26/4 14/27/4 16/28/4 +f 15/21/5 13/29/5 5/30/5 11/23/5 +f 5/31/6 12/32/6 4/24/6 11/23/6 diff --git a/mods/PLAYER/mcl_skins/models/mcl_skins_top.obj b/mods/PLAYER/mcl_skins/models/mcl_skins_top.obj new file mode 100644 index 000000000..845c7019a --- /dev/null +++ b/mods/PLAYER/mcl_skins/models/mcl_skins_top.obj @@ -0,0 +1,174 @@ +# Blender v2.93.5 OBJ File: '' +# www.blender.org +mtllib top.mtl +o top +v -2.100000 -3.149994 1.049999 +v -2.100000 -3.149994 -1.050001 +v -2.100000 3.150004 1.049999 +v -2.100000 3.150004 -1.050001 +v -4.200000 3.150003 -1.050001 +v -4.200000 3.150003 1.049999 +v -2.100000 3.150003 1.049999 +v -2.100000 3.150003 -1.050001 +v -4.200000 -3.149994 -1.050001 +v -4.200000 -3.149994 1.049999 +v -2.100000 -3.149994 1.049999 +v -2.100000 -3.149994 -1.050001 +v 2.100000 -3.149994 -1.050001 +v 2.100000 -3.149994 1.049999 +v 2.100000 3.150004 -1.050001 +v 2.100000 3.150004 1.049999 +v 2.100000 -3.149994 -1.050001 +v 2.100000 -3.149994 1.049999 +v 4.200000 -3.149994 1.049999 +v 4.200000 -3.149994 -1.050001 +v 2.100000 3.150003 -1.050001 +v 2.100000 3.150003 1.049999 +v 4.200000 3.150003 1.049999 +v 4.200000 3.150003 -1.050001 +v 2.100000 3.150004 -1.050001 +v 2.100000 3.150004 -1.050001 +v 2.100000 3.150004 1.049999 +v 2.100000 3.150004 1.049999 +v 2.100000 -3.149994 1.049999 +v 2.100000 -3.149994 1.049999 +v 2.100000 -3.149994 -1.050001 +v 2.100000 -3.149994 -1.050001 +v -2.100000 3.150004 1.049999 +v -2.100000 3.150004 1.049999 +v -2.100000 -3.149994 1.049999 +v -2.100000 -3.149994 1.049999 +v -2.100000 3.150004 -1.050001 +v -2.100000 3.150004 -1.050001 +v -2.100000 -3.149994 -1.050001 +v -2.100000 -3.149994 -1.050001 +v -4.200000 3.150003 -1.050001 +v -4.200000 3.150003 -1.050001 +v -4.200000 -3.149994 -1.050001 +v -4.200000 -3.149994 -1.050001 +v -2.100000 3.150003 1.049999 +v -2.100000 3.150003 1.049999 +v -2.100000 -3.149994 1.049999 +v -2.100000 -3.149994 1.049999 +v -4.200000 3.150003 1.049999 +v -4.200000 3.150003 1.049999 +v -4.200000 -3.149994 1.049999 +v -4.200000 -3.149994 1.049999 +v -2.100000 3.150003 -1.050001 +v -2.100000 3.150003 -1.050001 +v -2.100000 -3.149994 -1.050001 +v -2.100000 -3.149994 -1.050001 +v 2.100000 3.150003 -1.050001 +v 2.100000 3.150003 -1.050001 +v 2.100000 3.150003 1.049999 +v 2.100000 3.150003 1.049999 +v 2.100000 -3.149994 1.049999 +v 2.100000 -3.149994 1.049999 +v 2.100000 -3.149994 -1.050001 +v 2.100000 -3.149994 -1.050001 +v 4.200000 3.150003 1.049999 +v 4.200000 3.150003 1.049999 +v 4.200000 -3.149994 1.049999 +v 4.200000 -3.149994 1.049999 +v 4.200000 3.150003 -1.050001 +v 4.200000 3.150003 -1.050001 +v 4.200000 -3.149994 -1.050001 +v 4.200000 -3.149994 -1.050001 +vt 0.625000 0.375000 +vt 0.500000 0.375000 +vt 0.500000 0.000000 +vt 0.625000 0.000000 +vt 0.500000 0.375000 +vt 0.437500 0.375000 +vt 0.437500 0.000000 +vt 0.500000 0.000000 +vt 0.437500 0.375000 +vt 0.312500 0.375000 +vt 0.312500 0.000000 +vt 0.437500 0.000000 +vt 0.562500 0.375000 +vt 0.562500 0.500000 +vt 0.437500 0.500000 +vt 0.437500 0.375000 +vt 0.437500 0.375000 +vt 0.437500 0.500000 +vt 0.312500 0.500000 +vt 0.312500 0.375000 +vt 0.812500 0.375000 +vt 0.875000 0.375000 +vt 0.875000 0.000000 +vt 0.812500 0.000000 +vt 0.750000 0.375000 +vt 0.812500 0.375000 +vt 0.812500 0.000000 +vt 0.750000 0.000000 +vt 0.750000 0.375000 +vt 0.812500 0.375000 +vt 0.812500 0.500000 +vt 0.750000 0.500000 +vt 0.687500 0.375000 +vt 0.750000 0.375000 +vt 0.750000 0.500000 +vt 0.687500 0.500000 +vt 0.250000 0.375000 +vt 0.250000 0.000000 +vt 0.312500 0.000000 +vt 0.312500 0.375000 +vt 0.687500 0.375000 +vt 0.750000 0.375000 +vt 0.750000 0.000000 +vt 0.687500 0.000000 +vt 0.625000 0.375000 +vt 0.687500 0.375000 +vt 0.687500 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.375000 +vt 0.625000 0.000000 +vt 0.687500 0.000000 +vt 0.687500 0.375000 +vt 0.687500 0.375000 +vt 0.687500 0.500000 +vt 0.750000 0.500000 +vt 0.750000 0.375000 +vt 0.687500 0.375000 +vt 0.687500 0.000000 +vt 0.750000 0.000000 +vt 0.750000 0.375000 +vt 0.750000 0.375000 +vt 0.750000 0.000000 +vt 0.812500 0.000000 +vt 0.812500 0.375000 +vt 0.750000 0.375000 +vt 0.750000 0.500000 +vt 0.812500 0.500000 +vt 0.812500 0.375000 +vt 0.812500 0.375000 +vt 0.812500 0.000000 +vt 0.875000 0.000000 +vt 0.875000 0.375000 +vn -0.0000 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 -1.0000 0.0000 +vn 0.0000 1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +usemtl Character +s off +f 27/1/1 3/2/1 1/3/1 14/4/1 +f 33/5/2 4/6/2 2/7/2 35/8/2 +f 37/9/3 25/10/3 31/11/3 39/12/3 +f 13/13/4 29/14/4 36/15/4 40/16/4 +f 38/17/5 34/18/5 16/19/5 15/20/5 +f 7/21/1 6/22/1 10/23/1 11/24/1 +f 8/25/6 45/26/6 47/27/6 12/28/6 +f 17/29/4 20/30/4 19/31/4 18/32/4 +f 24/33/5 21/34/5 22/35/5 23/36/5 +f 28/37/6 30/38/6 32/39/6 26/40/6 +f 5/41/3 53/42/3 55/43/3 9/44/3 +f 49/45/2 41/46/2 43/47/2 51/48/2 +f 65/49/6 67/50/6 71/51/6 69/52/6 +f 42/53/5 50/54/5 46/55/5 54/56/5 +f 70/57/3 72/58/3 63/59/3 57/60/3 +f 58/61/2 64/62/2 61/63/2 59/64/2 +f 56/65/4 48/66/4 52/67/4 44/68/4 +f 60/69/1 62/70/1 68/71/1 66/72/1 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_arrow.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..4ca964a8d3fd827df873390f8e4bb15894a7b5bb GIT binary patch literal 137 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s70z6$DLo7}wCrIQxuon^L zonhefW(mWu%3lnPj2;EK&tW_w;WCBs2TzicX3PKo?tIFZcn`2ecm(#G<<@zU prE-cPY0<>inBEZYQ_TDfZ-iu|LcCRK7#J8BJYD@<);T3K0RT>SDun<5 literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_base_1.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_base_1.png new file mode 100644 index 0000000000000000000000000000000000000000..505331181a4ca12615947c1dfcc36a4736a679fb GIT binary patch literal 1136 zcmV-$1dscPP)W|U-rpzIgo0ILns9J#RCBgzjTzkwfv#D(7#?PU+Ja~Unnz$^rk zG)dd8Ic)XFiw45(LbMqusg-Km?Y7J1=l43m6E}LmzDfXo5dU`o<5>uRe!#v~0i*z4 z04M`En}qsbZC1px1EfS3Yc0C>4#VSV`*K=7UPF|!%44B$rr zvI{B8WTijK#6JQ!{sPiB0lbm+?`Jgw5}9oOmiD7N`s&NG$=8Mx%R+67)Gvu22jXXD z&D^8SoPb|15IChk_&m$uDcgK-LRFdhiim!a`x5|fzjiG!491?zIniijd2qQPK*larGe0LwFx@BzN(De_;<$*DuaM00s}S?(bV z;)R2lV62lfz*?I!^JSjrUTd8wrJ{v}g{w48eYe{!^?JRSh%7UE83@Y@r}@#7f)!RW zStDge#x;^U8`Mw603u={QpOk+MG-ffP2XrVV69bib91^}E*EH9tUgKSW=fi$Z}?h% zIjAcztk5U1ERda;0Yv1DF*ZpOPLjlHt$BZc|2+UKEiHXZL}ZL%Yb}U~0cd6}7@?lh z>W8FF$;69{D0~HgYPH(xVRY0gj~DbR@G|t zb5^8jsy8<`jbuorR;v{!LUx}3f0%>;6#zqK zreH#W`DIajq4=o?B@S&M<)_m2PWuGW>$awk1ZJB60000*?y}vd$@?2>^`3F6{sS literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_1.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_1.png new file mode 100644 index 0000000000000000000000000000000000000000..eccc15ebf39372a6a5c11af0350dbedd94a79e5f GIT binary patch literal 377 zcmV-<0fzpGP)S0f*=TjAP9mW42_S-oCfd(U;)4axINjYPT14{J~Q}hL`CLSOul6B zyGqPoy3T;n&`UriQqj0^0e~`;01|d}27eDXKtIqiOfHyA@0}Sn@@e^!>?*(5@#-FMSp6hV^SWB(DxC8zG XF1KeZaf&n}00000NkvXXu0mjfnLeP( literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_1_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_1_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..41f38d04f1908bd0f2a327fd96e7f8bd87066f82 GIT binary patch literal 144 zcmV;B0B`?^P)F0000FMPtl(A2{4Q_n!Y;&U4S(g@}lVh=_=Yh=_=Yh=_=Y z{RaEZ-Y_r;%>UyvZ)qF=@|rJ6YQWvSB%o~`Er%MCoc1oTRlwU+F)2ej??5ZH&+elZFNQ`bzYGII%M#BxocTc)L!ZjRivp1NQs0%KmxS8 zdx+CAuqgp(mrm0YkZem%fs`PL2&gCrbOJ|!)mEt@!GP*6>pyh+CFvXla%Seh=T<0# z!O)75U`~dv0~=;mlkqj_tO8HnJqsM)fw-n6AOT*x`tmG9qb9I!P-K za7=Z6!pt^w+a)tw15N_{a{ZF>#2GUSziYGOSqE-Tk7oSp*)E?M>vrJc)JWPF7w-AO z?HfKlnsH!wc0B7-BWa(@_c(B8W~|%i@;%|3Q?ujQFrSz|*Bj=IZ-m^v!_2mTL%Qi; z_-WvsN@1e;vb$G+6F|Yt&g)_GR+Z$HbTG3qcYhYnF|(8&Kts~+RL8mE?x@$m%sO=b z0PwicRbbf6`hiElCrLs3i*>r!rN5+dSTM7)y2C)!5U?uaH-SD8OI>JfiX=op0$ek* zs=MD8Nt4=t^FN=%e~Yw2qhE>gqr1Dp>4LoKp}T)kQXNz-34|2gJ^6L<_D%m&kT(t1 cT}DIj6F(Wt1GA+(rvLx|07*qoM6N<$f;7iQIsgCw literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_2_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_2_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..2758cf8b8567ef835c53a934f048b637c65847d8 GIT binary patch literal 151 zcmV;I0BHY-P)Z}P6fB*y_009V~)H~pd|B4BC%h8c^{THg&K*A0R<&Z4E_UevUChcCc#3X5GbgFh?A2``!@*A4k6hZ z5L_}Da1df`K^J2}3#F}TI1Zl38>&!f18wgI9{0Ta?vHoB?|UEjfWzT%I2;a#!{Kl^ z9FB{I98s4AIzSTeEIvt|TX_{IS^UYaL*Ugo1&AC`*AFbde~NQ&12YzH{pWp7mCzA& zy?_wjdEWw|e{6xE8%~-DEBDO>+h%8`b5)lmhdM`AL1V_FC6o zJk_PSm;$$|#kel!Cv~MXt-#CW!j!I*rbm5lR*UgbeDBHqnNd9UWazleTVnGC2m_yi zEmcKC3aZ)~%_AZcmH=I|_LqT=z;{&z7+SkaK-$KAKkj7cxO@O^1Dm$6pSJh|z!Q;Q zfw}g90}}}oAObuVk$qKtYa%_g=bf|QfJr;wr-5CdtEws@d%y!bW4u$<9T7PMW`S5h qkZ-CQ`SamrVB>6J# literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_3_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_3_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..0a97de395d75aaa7bdf84101d9dbf08dd8a3dd2d GIT binary patch literal 137 zcmV;40CxY0P)l%cIWN9_x=kSjYgxPKLZAQ~G}z0^)_CZ~gCE?Q?`j9sfC%6Regdb!xw3nN zgb=;nAd|^d?@RtL1_uYv$H<>gwt>@D3<$ZEcyZ>qZ*lGyqrtb8~Z!5W=^#v@~!p z98fNoKial!CK3r_dwbiT$z=M%;c(TmEdTFBA;h&|7$(5c(NSe)X2w`vUcPCO$hrz2 z@N#o=vl0r0F4O6BTuK>~Ql46t<;&%AN#KcL7{^jdA*J-2rg^crxL8?VU;hETa2)4z zx0gX9l}de|pP%o~=kw;u%F6!8$VjAKuY01!2b=|i!M;=~Hk)Gfnfxw(aBl zAcY@v85C{U<2CReNdCpzMv?VRCD+~-lGu~W*-k6Lf2F9Z$B7zOfFSS;cnrJ+`hg); zNxU2M33v{C^)yI2oi=A@XGa$n77}-)LYpSR|78gH0+>J;xCE-e8L$sLQjVx7y>UG` zIr$+Li(Mp>$)4fiVgK6N+C?^-jZRHX^+h6)t9U$a*|zNfQNZbjpCPFZX96+csdC1E z`ubO@1uzPQLTGn)x4yHpnlYAw($}jUMjp?VZ$WwL|5wJLeY+#I6hTB*C=+ O0000BHwFdLp1*Qm-GL$fK#jlKGTUq> t76AtaMizkwFQXrPyK8q?%C~`msi(A9fJJWV^_7kwy`HXqF6*2UngAFhEQbI9 literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_button.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_button.png index 49acf85503e8e297abf2caa4e43bad6facee0ca7..16801e9189776650ee97e0ff7e3a6f4ca8412a40 100644 GIT binary patch delta 176 zcmV;h08jtg56c0NBYyyrNklq>f!c1wT|n=FUtF{?od_>81u69I1g+D1-)q{PaB^>EX>4U6ba`-PAZ2)IW&i+q+O1b>lJh7G z{Ld-&2nYcZ$H6?R_6B?WZ63Ch$t3g5*4h<=We}oUG{m%j{_f^4Tn?AslpQKcD->o|PxNxjs0U7$vXQ*mnC2d$>D@-}d9#Zhxd~Ke`>Ap0`6DBRf=f zJKc`hEj#UZlXk!CAEvW^y}0=~9P889cP{{=2KZxVTw`L3r;bq=5pd#+lIJtHVR5MY z`3&s8$Ie{UFW_CZFWA|^@v@s+Iw5G z%RU0BX!fMesejBG8Ujwwvs=V1_yyEu-U+v2iUo{SuzBDvh7viT-N{p>Or6>+3l)Uu zU2}rcx#D=*l*J`iCMka0)SZByYFNQW0c$*XxniL?Zkpp2QjA;)EgiwxVDaTP-x>eQ zeL3oVq%M)w3oFFsMouG)!Q6PF6$qieF%1*nd7Fp4v40Q5G8haKX2k@vJ(i0j(4AX6 zd1kZ=)*HK)21(rx01?Ix2!(gGp^M;1_n1q8CZ56BY%N@Dax%(b^?9#QTo-fumtIw>_7v?^* zMw_+4n4j(BW({VM(*+GV34=2*<~)IM84Mty-GAWBDtYe)bAvOR92P}zV2#2cr_x{y z4Ejbcbh@~^nfu6_3I12Sxp&N&LEZnsoEg+@=3aUGhP9gKj>40mu?h#KmOF&4JD;6q zq&sKZbW}AL&5VxI9-Kd_4+K!OR5y*;M!_J%7_(2+no*^Y$UoY9tji8w8cp-q!9JDd z^?!pDe=L_yJhdY81@yP1(>)UAwKPu#YG7b?i>XEWO;<=FJCc zl~-&T8Iym;$-D{Y38#@(pehmeuUX4Pee60T;Nm3Tj->Prj!>H^{Mz#~VCGM#{Tks$ z>?vssvgRH?hn07>jN~51>aj%aN=)bU(SICP>S7-pg~0*qH2Jpy#W3;k#jciEB*#v0 z+aoVWhidobZ17XrsjTo0-`Uo+xN@=8tZK49Cd!!?X=OULwJM8=&IrZmpT_bM8^;w} zwOp`h=Zh}Deo-Iv9(iaqM`*ORm8&&Fz@g9gGV+p6 z6;Nt1m8D4`r+cADb-}C^hSi=gg2BgfRI%*h)jI6OfGucvoq}vLlz+~~pU_G4JDhzjof4s4uLvuwyq%U4?P;^=^$8{Im@584h%+KTUobl;kA25>CkV#9{x z%LLR6o$?UV1#e3@F>KfaKnH;r*r~5JNCNyy{D4^000SaNLh0L04^f{04^f|c%?sf00007bV*G`2Y=%O1q&)Rfd2nJ z0004@Nklc_vRd7>bm#oR)|Kd5K*_6c-08a+nhBfP-+b zQWQ#x(~e7;I6SplUTThW*|eJ-)|P2X+|puPKT`OF|bQD0NCx~H)A@T`9Fi7=AxEPXAqR_1yygvBjwR}1w97MO|2|X zx&Jh8odqfJd&bD-^7uVtSfmOpQU&W1Lz)IKyt2da%8q9IdVd#2d)m~w{x0?}!z7X^ z02=CKrd{ov-bA@iybuV6*gL#tZO9D3+Ql35v%QSF2MQ4PFT-RquXy{q064jga(WX5 zprfUcs%jCtBm(aRfRad6wMa)xBc@_kfZBQ)fb3PCY%UK#b5kYd${oHDo0jJr0hGJK z3aYC62uu$25k`r{0XW}W)EE?}D>3@(kyxBSFhu8|7qhh#v$d4YK`((|h)67MT;Mwc fely@7p~v6@;;5qQ;r&hV00000NkvXXu0mjfYvI)ua|zI zIw*UcP}kfS6V*{iNkMlELIc?;r`=!|-+lfds+D!a&ken&d&uMByh;CK!oE87zLCl9 zwTCCB*KzYEhaH2#q!As{9&$J2WvI@CzL6vOo&DH@{kq$Sf&97N-k`vkmDT2ho}-m- z$7aGLo8+y5 zrQ5i*X#w42k>il9{>mF={F~M#>uE4?hg(pxFwz=r8Ygi!3tnrC$f??b+R{w?gEOsd zx5Ygo(Ei0eI3|vyWXA?DKF%E&ku|ihBQAXY9{#HEs?hZex{p$gx%ePZC_wdkzCMU_ zs_fo;yhz;tC{ABMU35vj2;&L4hZ3cg1WkMD#T19XHLB?w9F|-(JjT#?{Goq%r&2g? z*{28s{g|6)+a!VR+&LQ8AdHEYyng4v1xlrm#g-C%F7T@~X#h^GJpqH$8vWxg&(<1K zrvKf9WFEgK({F<(*Wh96b{_W&Y{jGJlJfVb6UF68FuItEu2Ub<+ zzx%BXBS4Y*V|j`ajaSQVWl{R$J8+(%O@Z?QPP(4K$BGPnL$7bdv#o0uBL$yUt>;!& z4gH&LBpff5wjU%NFA=#yl#_wiX~KM{JKFED&{B8BVdKUR;yhTuBDbwRjQNc0PtFlSYNL9=toKxhnh(v~njhFwep}hq+bkPNi!YtYhL4wM_}^V!5xfX3XWiMkG7aXr;>y%Oc5gSbtPfOW{ym3wows}o5F3m@x@wyV|_ih zEt_Y){lcT$K%-?3L4%+ z;b{!X`G|sb9%_AZ@Y)PxbNsSZDI`$;vYMO@_xgR|7Vqp#^c5zVKhd0s9m1b@`29}) z!f!Mkdoy`RgC>zPjq)BcQc6mn<_A|~#tp*pbPocUlwlEGkAF8iaYn6Un9 z{WGF`F_rz2DLgrtT2Xk-#}SW4;@E;(68p}E8$UB*iJ>2b)WQjSv7)dTSFVh;NEPRu zdeU_=vbHRO(sSAR`VC_17Smm}m-hMh%XgX(RdM}{U$-xW-0NpwiJjLjewZJpAt(Xo z^?xPiSc{SE$~sYI5p2br%_n^sc@mf~)YuXsi(itQ!_WVvluCYI)`r}B>AhVo z>?s8tOnnY-8W+SlOOJMvQ$vTbI8ixqa_O?RWxRa#it#v*`NZdgqgR7kiCO@qi~)b; zk7Zb;V|bmq(a+Z&@0SI;TE*}-CJnz(hS5_#okdr(@vG>u(+sWiRS^39)m!43I6LvU z-hbh|7WEoA&lmG%Arspyv*29_!%M>ir+?Tfb-g?c6fcwg%+6krl0H`@@7V-;|gRfw;?J zzusb_Nm@(4hK-Z-CNo$1tiR-z9y<~@)ul0!^&Wu-G1jOyUuqgseEE&HKDKC<`ojra zPNv?7A&oCF;e-cEp5Ey+no^=hX|yR`PrS}QDP#mf+P<~t*k4nDnQ@|WBC`?C+dW(J zNjh7Nzwd?75PXsmsBdaHq(%$l-e*!C+vf#e>7Si_ci_>fvC02R4!kX|X zKQP1($U7V^9j~Ug>}Pw~ICF5}dqT{|RvHFnTK22sxk_xbCd8VmdtRl?@ZG0CWUJH! zFJgoSnFVeo74HS%VI7ZWGO&$x$>}kYF#J+|)5}uKvkfC&rfc`kuPDwiAT;c?l5iQf zwYWa8&muGD3byB+2jSk)#eBaOAyafJa}{Mg&QuHs6rNfXzHf$+r{hCMnz| z6{4}Rjy`I9?%?Ix?bR4#KEYd4gyoTw;F%)i{Bk9O z1eXk=3dU}4;n%@+GNi|^2|@1q1m|dO@-7wX+DkkBZN@iswPmLrWmOVELOflR`FwQV zCkk)%NVC~oOLtF;vGaNZgSa@7Z8LFo0g<7I&EWhfO%!I&p1I3fj^@@s?d)wgzL#=u z!n1MWNhUCP378Q?lri<+*Zbiu<=pyr!3d09@!2lz)d%WOCp}^x!A#Y!pIB45g9d8F z8r?wYu21eU&O`hR1RTquVF{m|q`R^IM4s<=&31D?~h7rL_i5US>f+|2O%< zLOO9dItvV1CTU-yuJi5Xa5psGz(a(&-r~Cso+1e+DFRQ;w71koQQJFEva`c=fFu2$^ zuou3I#t$vm9r?a;n>t=2vJBh+xv2ZUT{<@CZF!FUUp|b`>cOfr|ykZwKSj!k1 zxsfWr$>7?*Lok?|l%l^(2Z){C9l;eC+eF$k~OJLH)toYVz7_Wlq28uB5Bm%TW@{<2u5HM;THGOTS zUf9F!{2=DNp2b%lFZBHdDFd#3^~m)m$Jpq(V{QS2g&~@U#DH=<0)uJ+gkd;SpC}S~ z@0PA5pUNgE>5}d4+B7k%5wfTG`fNIQ4-|VM$chFbyjf@y7-&bhc=B1EM& zWm%wB+AQO`?95lvv}YWW-VCylI;WhK^K$`80b@9QD?}Yg`w`6v)BOsc8E5?Ar&%wc zqVcKp8}OS1RV}yz{~02D>*C6y=BX!cX~D7IwLe`W(=nbxG-ZrcGN#;q3TT7PBr2IA zf1j*|l1Z^|yu9M}O2M${2Bp=NbK%v5nW%NrVNh<#?DcD4u>q?gM^cfIU*Y7R#z#;n zu=UF4JYy$qsQgXr>^SulHO3rRRjp^$`Ow3GRWFjh)>H3ZUjZieK<49IJE*d}{%W?C z$-K;Bjrx#K=GUr-C--2lV<&@dnqWFbHJUq89BstWI8xRwQ>7NM#zP=>Xik3k*=oSY z+1Yy08@^X9@Tb4DpZj(&zEaLec|}U{@ZZ1at3`@UKZTZ_B_n&CV6mMA%D55~r!&9e zLyKYA$eCi96U~IZaoW82IYuD-Zo5bp1 zOo5&GC?|u^cYiMTC7;c00JGLM)zPlum!X#I4CRFC{_)qg0uWxFWb3UpV+BwDt+=}L(H}ANms%3CqkD~>=?)oWc zCDo5#JKw?YjNrR-f6PX1%@paV%cHmU2m9wz>-yB3f0cywY^&KtS#I{b+*oJ~40pR} z-zN>fNX`5PQmCMKM^Tf9Q)GdSJTr3S2oExtkrB|2c!@2=$$Sm!xQ)iYp%olGHtAF# zoTQo!E05$Tv(DOUlOzb|5Dku{jLOncSkQLe>z23hD3mq*5;6G!)jD@Ag~cA~_VrA! z3adZGCB3q?E~6YfN=@o9E#!95Nd~1DHk`=$jhw+!S>Y4pH?wO?P|qF~f@(6#rdhEw z=&QyKsrDfY?~mG)@d*~YgE>(VL9zIuQ&XdahH!h*xxp;3Pr)bco`a`R5>4Giw~IaiG4Qr}4hocM&!IQZ@Y02ZL}PDcR%07gdU7n~e# zgoU`Y_+HsbOZjUl^Rp?u0?SH@8_5VdLM7BxlnfyXex}MFP4tcI(p>#3AdzOFcG^we zPB{^d14+SC73oXO1$$qb_Ykck$obXXJ>Y--=l_EsnK}so05CkYpxS`+_Pou1!%|gA z9*D+afB*o1?*=jS006?L|AjHV5_AUu0G_9^ngZTmENn^+GA(S&7y!WJQkIv|fs7QS z$N1HP$Rb$d6w*?3jJXiEQm6v(dg}0U1ES;!`y`TgeOG6b{^PiM%S;yws$&WTs87?A zD+eSJcuepBT2%X zu%^bh{sl{)D_sa%ZWvbNAmJyku3?`ZT}SyoS+1x&l3GyK&I7|=bOGdn+rIpzcMFS5LiTUZs5yCKsit35J%gdcxDX{lK-k8G&*s zV4l^B$eeVVN%kkNxChZK*?iatnJ0Pcce}5`iR&1m6V3^N`x>?jUprTU(WlGH^G^tr%OT z4fOk98Pif5s#~zRTCdKPG~Z)3J`D{#Sr^5l@7;YvE^1Z+enJPVieueGk-hpvNhZ6# zMl72CeKh}&#;UPyW!IVpqqJ7&y@|+j(5 un6!?&^^VVTg$kYlyq+PR_6*k^}qD{j%TsON(>ASdXw+I@nmC| z|D@L7eRJ&D{rdC2}_-Dfa0tb%I XF=tl$Kl5GlMiAH2)z4*}Q$iB}5*JU0Kl7lj;z^o=QUgQIr5tUlBC!2 l6z;VoNn8T}0000!=K|6e5lhbH4e$T}002ovPDHLkV1i2PEph+= literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_eye_3.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_eye_3.png new file mode 100644 index 0000000000000000000000000000000000000000..6a6ebc74d1f358595974188a978b57372ba7fde5 GIT binary patch literal 121 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`Fq=B;e`d7?N@C?RiDM0}2ex z4n~GNN%tdu{Quo`D3?>LX!)%r%a$@QFw{?4vVGRg>eZf;g!jd+KKy;By)gp=1H*=? Yj1f6ppV$6Xxewxcy85}Sb4q9e0B&C?I{*Lx literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_eye_4.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_eye_4.png new file mode 100644 index 0000000000000000000000000000000000000000..1cd82bd485b49362b7a16c8060752a1348dea6d7 GIT binary patch literal 136 zcmV;30C)e1P)blCdZSptc$EoDL&iCM} q_kH(|6NYWcaVq)L0RR91;5!aRBORILZ z3S3=I6C+3)h!?_6C3(#5c^n1SO2_uVy17k7ZTp00i_ I>zopr0J7U3cmMzZ literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_eye_6.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_eye_6.png new file mode 100644 index 0000000000000000000000000000000000000000..8be76c3175c121459cc861160a31d707f9fcbdde GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq@~;)5S3)T+q0`~DJ}XW&j11SpBajN^RFvbc@hf}@O1TaS?83{1OUN; BH`@RJ literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_eye_7.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_eye_7.png new file mode 100644 index 0000000000000000000000000000000000000000..f800a90b7fd2cfaa99735a7e72f2817ea5fda24c GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq_BG)5S3)*pcU;pw3H=n|tshXP^85nFra$kE{GBYqRFxfE=Dfq|JJz$e6&fq_9zPEku; z&BD}3BS_CA!@<5f$Wvd%)x_Az&L-N?Fx$`8*ULT9!?h~TvoJP1I%9Hv^-_hM%vu9l=GTw18*uWO>rZv!DQ{#peD-1Y3b21A~ zP`k-cCh*``T66A0=qiE~Q$dEOadAg;hr4A@GJYD@<);T3K F0RZVIQfmMJ literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_footwear_2.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_footwear_2.png new file mode 100644 index 0000000000000000000000000000000000000000..dc0ef6472a81a0fb2380c6fdd31066549edd0496 GIT binary patch literal 229 zcmV^P)de7>)I3x;H<&61DY#9?HxcwL`2l? zFmwU*q>51l_jKq}-0pi-3?gs$=MM&|pZ*F*AU`ao!^1Sedyi|^<-|cG-@n8fT0m7b fgrMKXe}DfI+45zk;Q8$q00000NkvXXu0mjfem`7d literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_footwear_3.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_footwear_3.png new file mode 100644 index 0000000000000000000000000000000000000000..69bb4d934a8ad11ee03a7801d0874e4bcb823518 GIT binary patch literal 331 zcmV-R0kr;!P)!*WxVn{2j)I67D0z|YzCz!i&(l|sP7y>16&%|~C<#e}<;HuvxjL)o zH=W^3ABO`UD5aEAN-3q3QtIBAOAD*jD(v@rmdhoZ&4#ip%`F8GU0OIC4lEW6ilQLT z^P9VXiveU=Mp>53=W}+u-TeiyUay(WW^A`xrqiiD4W*P)N~xPELseCUx~{R-;+(@; z%j@$aNo08Y_{KSha}EFz0l->I*L8>p@jTVK^L;BnfTXG8haHk@M`mr|9~goAOJ)}BY=r}RJ+#FLP92&Wyuu$XDJ#H(G|c~ zO2ucb2(a+oTgpowzenu#HF}8zsq&ej8O|p>4;<62L+s7T(ta<2VcuW7$gWibyye{- z%qd=6lqI8}&`A^DKc`QPZgemTnqMI^uKeAC;g}5nneso@ssTR_&?-I=Jr-WO4x_;U|` zgcN{;!}+|&&t!u;IJGiB?7jFkj{rsKc!-cnMewHZZ?3~XN-mAOuSM1e07pdbq?1nS ahQ0wk(6l1AOljHx0000ES_WTe~i*~576cO*%%0p);ch>N*;*PMlqWFNK_{PZ~$B!d-+C0 zfjY<43;^tLI00Cbf9voEKt#mMbH?$B2Eer#tAiNA`Q`%{A>^9@;6(&g^GX=IhEE)T zQ(?bl(&9aI3TOe8aoYFHBi8hss&6M9tj-6pGV=^zXXa-tt@3}lI>%k1`Q!og)#q$W zYsn)@+5000005^CO2}^g)t5KY0!8eoh*Ryri)2}grK*KGy WvLJT-Vo#P}5ZBYy&t;ucLK6T1pgm~- literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_11.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_11.png new file mode 100644 index 0000000000000000000000000000000000000000..3eff9bca4f42e17a149a9c8fcae33fe0509c3c8d GIT binary patch literal 454 zcmV;%0XhDOP)-q)xXX-C(I(|NlpBx)~|MNeq>$ZVbp>oGNk?2t9fwz>|;6j!y19m287Z4F6qZo21gMiDAMMRy5G(^;8>@k#H z0>}t-NL<*01^@sn5vS5J{4fDF`+CnIF`FhJLIh`)MG>civ|qC-Hyb7A5oPB@%jAen zy$66c)7RQ}9wmPfa;sE-w{0%C=LjJ#(lV3ZoHI*^$i;UeBI;C!hNVj&+22K^4+QWH zz^7WC2;9w_B~qn#GP=_)t^pB8TtxKF0B!)@)t*BV!ueoqD2kkdDYTmL_AfN0vV!L8 zi|BhsYIO6fS$hTWVglnSam*CYr+0zSanJHyf8R&e-?SWj_WMxu#)4f75tVV|H+}s^ zM14qN;+y_Go0?wD9Po%kAF1gvk!@bfDWE6qQ*UK-UXqBiM&YfZ+H>~*;{@>D>wmWz wP|p~BH(dh5UJ2NB?XS8E95`^`z=1vE3t0@j03UikJ^%m!07*qoM6N<$g6PJ^^8f$< literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_11_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_11_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..05836b28825895859f2d1e1de6288fced1ab60f5 GIT binary patch literal 202 zcmV;*05$)KP)wldQ0o4Hp2W1MoxpC@DX10001xD;22I zuYE#f^cP(m5Lp4cnqK}G1mCo2bk6{9c3w>^fjbwD3c<9AvU?w(ie%%j*Q66H_6w-P ym&q^$005w@0VW>SH~;_um{b3ya{vb*G+P(LU=%cm1N`0q0000}bJ)g$msq-5gvx zs8ET^|3P@vwmRr*y&pW1OLA#)xx1uA7IOi-0H-s`DsaaNQ(9uo7W@d0e=184(Vzz8@5o`F}@N5JkEx;sD&fF9Ehyztu-1102f>Hh^*_RL`kF@`AULXR07#EbD2JqB5gVeN z7Y}HC(U$=4`omLEf=oAf01TqX(8dh?*q|NFM^rNBw||X!J|3T7cEJ~O5~AZcj^j9v g<2a7vI8Ltl1Y>Q4{N^@AmH+?%07*qoM6N<$f@i_i?EnA( literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_2_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_2_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..9258217888c5ebcc204c36d2305846ae4af53753 GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq|jG)5S3)4tEOr-1#eE^<-p^wOu@C1DThVGS;F%p?unZ-sXYG{gz3c=qJ-(4E{ z?BBi~oIq6wch9Gc*iW2_2UZmkja z%mhE<{g~T@##ULayZi}C=>2#!B`m{QY>t)LRZvU~Y%GX(BJwuD&jRRxwfXpZ$pAD# z(o1tX)_N1>c0eN{dmo2Ql|d!`Jr6=HBF#`$)?cPj0gr6HuhfPn?HQR-|i=RKrDg1 z+4mtBQ+NbQ5qS>vc~q`JVP10GRlDHWh33qQPBHe4c$qT0ux7Rz``xeLoB&LDcMyy< nNs=T*i^Ix`xCy49m>gTe~DWM4fJ=s5> literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_4.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_4.png new file mode 100644 index 0000000000000000000000000000000000000000..61fa3db8c6a9868a6a5035f4ab2c2ae41f7391fc GIT binary patch literal 1097 zcmV-P1h)H$P) zdUn48EH--pWcxrMey9N1N}Q_#J-`Ie78D#!B{-hkF9Ew!605*;u9s}LNs{d|z_g@s z+w&pNF-cv8%F(bC=!%nFK!3*P6NH|y|9qT(GjnHwebEMsz_jh_wiknd60lcNo9%Nc zi$4KpC7lkLp0d5x3>>gOyFHfO8weVnjIbG$RI>d6a9L76&;eYRBw*h5G=QYL$@@jy zhiyNf>TyBRbHKB}tCGqoldm^C1%Si0rz9;W*KgV$4jPsuT>|dd?vYdhP6MB3{oBB8 zV9a(o&!|c0)4)W^Dn&<#ZM5#5m$UZq5aOkbzaQdU zPd~5%oXM^aO4WMS@=5Z+Q$-RK7E*MZA9f2=S*8__fyPB?TA zNFL7lM1rzAC~9a5l(LI+z^Ux^YjNOv+ZQ&`^p1n0g>p6ojN2YfzAvXkEOwXGAga;~ zDe$1}tuTK%!Kp+(4**X9U$mMM+^*e>D0*XqxgT3m3UAkz?&JKoO(}&R!ZV)=`KiDW z?NNhsIa=-yk*(Ny+sC3N`=SY^jUGH P00000NkvXXu0mjfZ)MDhD6A*MWdH_X00v+H%3{HsU-1SzzyO*7 zp!$lt69CE%Ksf@q11{YIRx3L>$z#v}+yPs&&pX- yo^f*r(7_!$R^gnuD=`MI_;F^Z$I354@_GRv(g{S$rrm4+0000Aa$G4&47O6&!o{sHh&YBoa5g5TKcj!OblH+!C`lFp6JltTn7YA@ zWcOrq1_lvf6F+&=cR-BLdwSo@ojd2=7hEDq-H50GZzL@O-vQ4fVoTC6BF4Zxa2r?x zE`Sr@UtkD~C`NVQ%yX(o#94N2Z3_SGwW*RG06m~CX;V@kXaf6^I-b}x?G?26-UO!! z>}P@bYJTOi8zSNeSOo3?uOs3$unn{#VlM5<6#ZVn;yW21ppp3A`PuR%wIr=eT9Fh$ z)t_CU#*8JY<#EM770Rz%;htth96Qn#pS9b*HplGM^q6+~yhwia3P+#?Y(&I~BR({E z%ai+UmaCsNzk0q%GhnP?J=Xv<~!L z+G3()<@{Xp9+y2P{$$C^`ID+;p3=wzaO{$D0gQpW2A;ac{^bUv6%j)}-~;f3pD_YP zlHMlA22Lg2_4gCty^ZTXU<3FDs5rp*-kkp|n`D@e`DFYQz=Mo`ZvKzi;y3LXNc!aC zw3z}h4}1j1k~X|^X<=uE4TZ?fR=pTd*&ZZ@H@b-Q}~Z1Z90ozI*3oa=4DAc09{E7KvUB9{yuP;)lw>%z+(eL(wd*u@dRp4$tv)Ro0p$`E!Fr1k5l>9G=56)m?)j;-cIIc*hKs3`nJ=p z?#buv1lU}S=B^^j=SAcOu+yagYoWKb9){V-7E5V`-?H@_0k@^6< zm=V7Ryo-oeel_mcCoWu0k0Rn7rAn15RjO2}Ql(0jDpjgfssEim1MxJk^}+L!I{*Lx M07*qoM6N<$f->Q>TL1t6 literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_5_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_5_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..ecee2e2bb348497f15f2bac3c6a6aa43cc82b7b6 GIT binary patch literal 282 zcmV+#0pXHB?tb^#cE!@)jpFJhe_sH^IRs- z(MR-j_|XZE=%cZokp5BjV4BIh7%Z38PHVcO{xER7n zDnuOAFNQt`BB0eeGrhHZQ54b1;mnk(H-CSVEgroYvi}_En7u?1oYm*Ek+%FuTL>Y9 g5JCtcgb)k!1Ms3dF80UyZ2$lO07*qoM6N<$f(LMS%>V!Z literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_6.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_6.png new file mode 100644 index 0000000000000000000000000000000000000000..40e6eb759e25ddbe5b9314770055233bc6eb4eaa GIT binary patch literal 680 zcmV;Z0$2TsP)1k&W;_yuRqnK6bGTI8DkX4@o?;sg@>02(=yIz16!gBza)K4`4 zTtrw*KJPod|6*K4IksG^&+EeYX5_5_z)Y%ut|nk5qlPeLD-_ibrUF(nK0QbJU7rF~ zl;dv6_x}=LUKhrbMNqhE>|P2`<4%_3Bw13s+;GXmM?O6#J%Z`Jek^GhO(}X85f*bg zpPh3H%d#8T3PqouV=ELJY>Y{INV64+k~T?OpPu8>b2_d7+02nta4=1tjU00;jb6O; z={bG*A_}!p-8^B#A%Yq{ZRZf@eR@v7N+#)eGTKQoM6`|zFu4Htl&8ZX!wK?K%a4*j25vittx!xl++br& zM3IP#!?K&)l@#dx{xKXm!B*YHlUVD_U}_k@S}|5rsj*v6BKLuu&QEPd-r62Y*bgeI zit=B!mW%bfR6u(Gx92rh>VTtzz&{AKQNJn5(yp?JYxpL`F{ks{*^9{vkIc8xFHBjm|`Gv5fNiBFX*r<<1DC}44503m~!d4E3p-+5>nwAx4qH5PdJrr6Pjjt>jwL-g<4%{%ViK_79Xc^cs4T2qKnJaC&fK*L9Pul<2N?Ak6x9 zcF2tLky)ad62(&k&on&KxQUJ7G11Wh_W*htHdp+q!a2H=a-SU#JIJH}3iS*WRv71S&quzez=ea%H-I64PXLzyzBJ=A08_0d*v`&RAp&e^ z5PbOWQv{(ELfc+mbJpt=U`3zL8rmCbz6neW4c`&@(IY@aIwUj2mm)F)a78i(umbR^ zow+r1L?Y4w@L}lakX#!2OTAnBKBvHo{zDls0RWN@3SON;4Tub0{}enxU3B3%)g zknAhGYtbDwtfP>+Ku&V8DIDu{QXw0K6ai69rOwMoH{RG!8_v7zAKd}gmm=9OpT<`5 zD^u6@QYGhw;ae$C8enpVKELAxiw^7B#j(DO!~4=Gr2B!mCB3QT<0plO6t}2*Y>5mn zyTHGu*n@XCYRzcF0hx%*$nE+nBF|Nozm!+JuVbO6K;np%Q(M^}oC7oiT=#Ng zJU)owZAZY+5wk_c@D#ehbp@7GM8#0?M8^(sS<;3B?)HofV12Q=gIUJ$AiBV`0)Myd zsrv<&^Wmfb$wwDVg?pFen>HzWGbsI~6Wq99x)T5->ZWP4#+lC4I{g5UMb)QbbvFY5 O00000w85Qd*ONz*h9Nk1U8QUpbzB6Qb<6oszb3F1O zMG-_qV#vaLye^!;F$A@%=HonYIp@xud${x7b7ltq&8h7=(6U_tiok8#McZX&oWg(j zJWS?8+bh6lU>T^-y#Th~1GTvAB|$F(ow*l4(k-A1ypVJW5U>dhB;8nqBk&Ta0PlcJ zNz1@hNd@55A{>DsuoB}H+ihSY9$#F99nc59NV)*Lk<^`sKYtbhhQJ^a;dR?fwx0o8 zz=wGd;Mn$3)cFRm7q$vejYL=nwr!sP4M}%^a$E+E!nYdtk79lb6m2W%9U8#Xu(hT^ zgv+*Tz=7>5a1_DsN6jZb_MYvnkto2f?Lq`u4c}%2)k@}Tz@hC@2wVNVq>HxK&pmqE z1=|}jHe!pfMZncD-<=6d?8L4a{p~_@kEKL_QQ&_F031%k5hwwx(c*R_^(1|_{WzMP zv?usDVU3Mwi0($NsDy6~I0>I`BRjAJT$8j7+&p&yBsGC`U?^#jJX=k+``>oZTiag~ zk-D}Y*zVZwC9XfCr|1J^+drly36>?j9t$2xZAqUJQxn*Wd~lrj^(D2(-tC0_eqt`# zex7OvJei47VS9Cgxp~HAno()$!0xP-%l#M+5;2-&GMP*!lgVT literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_8_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_8_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..751fb9bc06375aad4f61fae2df3b5502b5272cb1 GIT binary patch literal 172 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq|je)5S3)Hl>|D)&PYm1M@;EO>R0+}AVYc>x#b^=W# zCkw*Td(SenJG(n;;J7uC3Q0A9sib7j$@c)U(l(qQVJ0NQMA^bXjACHY9Qds0RJF~aQ|fM3p>Y;TxdzzW-z zWRlc*g%4-8!2zp~8p-w?Z@b$;TjijZ$`|;g{PEdF$6EX-QC&lPzXHqzm3#A6Y zbTKdG>x+3QTW{VN>k}LRZ~>sQO20LVBGS?#)Y;X`2!ECY013d7WHKgf09<++8B6jO z`&O3!{@yEfkh@+O+ZVjJ&E|#_xq+Cl|?F%EbYE?&>nr;yA1EELgZH@OOoFu-G?r*1~8L!Px5x~)8K1{ zrz87kKRtfhnC!!+!2hbk8vs`TuB^pg9Z{lpQG*PrOT1QEH(@Mp?P?AHYJ+%+QoDGe z7#oZOQdEWs>5rY27UI%WnGhrsovz%xL{$p9O5d%?xMxb~9u zQPhC&cxSUh-yV+ChGLWqh}QkAPKx3)HDKK4{{wtzsrlg@@M#0Lzg#kTbuau(cK`qY M07*qoM6N<$f_Mp6uK)l5 literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_9_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_9_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..a5ba8f9897df87f055cd466d63d315f10ead9818 GIT binary patch literal 243 zcmV9B5J-Ih*jT#q1Uv!@0;v$u zw4$_WZob90I%Y_RP8}MlwIYA(Ir`~;KK;(o5y&_XHnvkSO^{`YZ$G;LY^>dcf`~Wn z(;2-M=E*N+UBGxaa!DWzeH67$f9#@ab>h%RkrWR8 z4Nz+-M#EsQJHlwUu$^P7l`@_cP*zIBeuP%naDAV?ZDAM&d!2n$rG#lV`Ss^7bzMiC zPKg2sNiI{AWlo0n^$U3Ts+_hO8lG$81`$iTf$#gINrbLySd$R5rC^Ue2E&N;&0Bau zpVP^NnpDT~#~-*%A8WnAAys%coZiy~EME~}(zf`1wl#TjV8 z{pS00xlx~0+&Qaw5TmPS6;Be*ueWL{7wxY|0_T5@cQlpxIj literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_2.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_2.png new file mode 100644 index 0000000000000000000000000000000000000000..5e288734dc36b8d4371e31cf57f31273d809be84 GIT binary patch literal 886 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-W?*2L>fE=Dfq|JJz$e6&fq_9zPEku; z&BD}3BS_CA!@<5f$Wvd%)x_Az&L-N?Fx$`8*ULT9!?h~TvoJP1I%9Hv^-_x=To!D$Z=oRtjxr~uy4xrrz>5zoqMyA`O1{#QmNP8<^4P`T`pUifq{WR YiH*aWlO;A$^#_RO>FVdQ&MBb@0I~@rb^rhX literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_4.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_4.png new file mode 100644 index 0000000000000000000000000000000000000000..1b278d5b07f233e848c637989d27f9f269daa863 GIT binary patch literal 125 zcmV-@0D}LCP)5CW6}006&KAKNFB-7?g&=y~z3>*IUQP@m;&W_{l7 f5dZ)H0C1=QE*TN@@dxbC00000NkvXXu0mjfb^9!( literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_5.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_5.png new file mode 100644 index 0000000000000000000000000000000000000000..0246dccdadca725c2e52b303fd509b540b26a1bd GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq}u^)5S3)mdKI;Vst03{kGi2wiq literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_6.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_6.png new file mode 100644 index 0000000000000000000000000000000000000000..9c9ab1a027636b3fe45c5b9dfde5691bee69d5b2 GIT binary patch literal 140 zcmV;70CWF|P)f3W-!008{g>|T^!Sn^g5X0~x45l#_eS$@^k7C#ZjA1Y=>=DM&l6*nLBx8s{#9-RB z+{tXFP592Q+{-y||Ce(wA%qY@2sPDMknYjiDfV!JBfOx!(_iP>);mt|h%c16ewWt* zo4j9QF&LOkr{Ecv*jN5-QPA)I%5Tg_pSVCXA9RLhS+ZJrz}p`td5rV2q}`^fEb+0^ zzs?t3W6|xJRFxj)*hl^ouFx6|na_Xn_i9WUlMeCKN2E|^K|udS?83{1OWV& B7KZ=; literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_2.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_2.png new file mode 100644 index 0000000000000000000000000000000000000000..2ac147e31d2b682cddfb5c09bfc2f86388cbbff0 GIT binary patch literal 122 zcmV-=0EPdFP)&aV{! c004kneFzu{oCC!gng9R*07*qoM6N<$g5;zm@&Et; literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_3.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_3.png new file mode 100644 index 0000000000000000000000000000000000000000..9bb46f6182ec4c63149121d47248d7de5088717a GIT binary patch literal 139 zcmV;60CfL}P)>w+008_?b+I5;#3D|8-#?Al$002ovPDHLkV1mboG~56H literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_4.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_4.png new file mode 100644 index 0000000000000000000000000000000000000000..a01f7ed05e4f4f86cc20524c99713c92b892f9be GIT binary patch literal 129 zcmV-{0Dk|8P)w literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_5.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_5.png new file mode 100644 index 0000000000000000000000000000000000000000..74a25a93ee017b6755e8db0467dd35cf2fdaf265 GIT binary patch literal 95 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq_BI)5S3)LmK85kHCDsmW?rm_D#TfCzL#PxLbb6Mw<&;$TKq8dp6 literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_6.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_6.png new file mode 100644 index 0000000000000000000000000000000000000000..3b93aaeaddb2a9cd86273ccdaa909d511ea4cc37 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq_BG)5S3)^h literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_7.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_mouth_7.png new file mode 100644 index 0000000000000000000000000000000000000000..0b1afb994275bcbaefa3e354c56a0f457ee21a6e GIT binary patch literal 98 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq_BO)5S3)=^9ld}002ovPDHLkV1k}&KeYe= literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_slim_arms.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_slim_arms.png new file mode 100644 index 0000000000000000000000000000000000000000..5e220587e90b9176e893118d7c932a21477137f4 GIT binary patch literal 93 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7R6JcALo7}wCrD%*=y3jH wzwy;fjnacF7-uZ}H9w?waifI}4+F!(>rB$s|F`imFfcH9y85}Sb4q9e08}p=2LJ#7 literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_thick_arms.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_thick_arms.png new file mode 100644 index 0000000000000000000000000000000000000000..95b18992472ac166f401e125d567443af4c6821d GIT binary patch literal 93 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7R6JcALo7}wCrD%*=y3jH wzwy;fjnacF7*{O(HD6}$;zkP{9tMV`=b5B43LYI`U|?YIboFyt=akR{09b$=R{#J2 literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_1.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_1.png new file mode 100644 index 0000000000000000000000000000000000000000..aeddf5212f395f36f7a49f8b6ecb46535b83ad3d GIT binary patch literal 606 zcmV-k0-^nhP)B*66vzMSbTJn=@)5)hg&6t?`T=@F7k9qd;C_M|G8p1-5J)-(x?PqGr?EpmKry7? z10yIIE?LZh4>g;*SVj>}VsO&*sD2>yh?Ixki{3v^fW>05SS%Kc#bU8oES8T3IfBnt zaD6GN76#Lq1K_2h|1JPt*c8B16K7|Kj$TR$0N~GmHio{|5U%;*O`V+`^LlkUZFD;A zcU=MpPXHmL3|>!!zSa<``JwM20bWs;T>xI_dtxx1xmlK%8?r3NU^;WF_7`(YN?8s7 zEdZ_1_oTA5QKbpyPJbu2!#!@!hhf2_YbaKuU?w z_rzL=QaiTPJ=bQwWBuqQa9#{VV|KF^0;7H~XL0JVICZ3y+z`NWe-(Gptyl|zXw2MQ zLR&|SPa%RyG-mElr!Snx41l85+4JYnuvBX_;EA|K=RqLVe ziRa%Oz2U@_Qq~Ec*8J?KjZl@)sOF^m zHZ_7b1316B`1(`z5&B#xwOrsn4RbS!{bR4 saFEAUl?D_xHA;@^?}a)VVEO300w0qIAEhp!!vFvP07*qoM6N<$g2&w%wg3PC literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_10.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_10.png new file mode 100644 index 0000000000000000000000000000000000000000..d7e0191cd17845dcf7de1bfd3575c08c768120fc GIT binary patch literal 392 zcmV;30eAk1P)v0IK?Z@gSlhT+TJ(N6dROb-Zz}IKHZOs@m0v*VR^UGhe#* zDEjI>l`r*?h^mxq^o(81fN{wz5e?y*iRjB@{~3TpXD)=S%nS~nvhg0Axj!{Gz`kS< z^F~A;Vf_x^m=mR{PXG=k?um%b09aK&V^gew(fY-h#ajmSE&3{C`4|QjjQHGKIHmT8 zNP-YaWczIH$x0>M$AF~;!t$^PQ&lW2kocMugk~c+SN;-JgxqBYWHQPrktqX=X}{;g zSvDn&E7#K_hTv9vFZALDOF_pd}L=rx`!TO{zT&Hn7+L0000G)P)L2n9gebpMrKSLlZr8t(?c@DySd0001RnyaB^n$OJ2de7!yGwlW3r;k8a0Qtl1 zui63mSUVGY>>Pnizx~c7IKFX9Pyl;IVCrYh3lM++1OQd_0+ksG9TV_-sQ>@~07*qo IM6N<$g0QzZkN^Mx literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_1_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_1_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..64df0b039ad1e3b86502bb33e8cf621513dd217a GIT binary patch literal 131 zcmV-}0DS+6P)&3IG5A_{|E;?C_a=bKd^_1qi?&kl*>yceDZm5P$## lAOJlerUTvosUENjMmzI|1siqD?x+9&002ovPDHLkV1g5JEX)7^ literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_2.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_2.png new file mode 100644 index 0000000000000000000000000000000000000000..5deb9f8bbe14b771c2f1781750f72fb74704dbaf GIT binary patch literal 568 zcmV-80>}M{P)5gg7=)jZZ7EScNCF9=r?iku$^ZW?J@i(3DJgATr;e@2(?dsK0xg7oAg4RC@3f>C@3f>DENKoXE$tLK701I_kMAE`ad|J+9d(1fBb*#&h+aO zFta@YIsi$BKo2Y)&6}i-fMw_-tR!vX27r6u1MnG`+rEo9 z52?|&fFeXAsgHf{ZBOEehwN$%tbtjc=`z;9{ubG9k3w@fb_cu)c|!CKu%vYe55yXv zwmn$AjsW`+V-0M8sqIb3*Sp|=%62Vj1sq0zS;W}bK9#iC3c+EAkB2##zey?MQG~f2 zdk9v*N&3DE$=>!fr@|t;yAJuv_F(m418TrqEpd|T?r%F_`UhITS#&R{w>=1QXZu3Z zmx$t2C22VRx>S?3^try@a>wXjgwB%S)sGEVD`^gNl0L@jt?ilZQ`--NU~xqYtdbR9 z6QGstHhD360gi#S?Q`2V+4zx1Z;)vnp>Amf1NpGI}2h$X|N!p+1x5>Z$Wd05`vg%y2@Fk)E0000OZAC3Eid%PaFaDtc-3cySC=}cX zZfnsj3JM}J&_D%Yrlgom-ZY6bc3ycy-{iRYo?Nrgf|H@>``|L~z4N_0_k8Ev@6JGu z96562$dMyQjvP61f2GncYMd|D^<^)_hJ4y;CbNHe#|$t2LeR( zmFnV=6DO%Ie@%7y3P(vsM{&RX7rV8@K~_AV^8?tp?t*s(0F& zFCBycn`&j0{5Qa3zlA2bMy6-i)vlRoJ>c$5 zwP+IXQyqt;V7@V(@x#GUxo7Ct?|?LL<`Pggv#y!l)&4A)St0}M27JUH1E$UF0Puo- z1dU6886BTb0%w3TAH4hikHBf&Kdtzzu1^Q|NB?Qz)`#TZ434JE&@y)}0&nSG+o*Wc zO0K9@O@eLE23`WbSA1m0cRr8Xf3<=nj)~hXe&4#q?ccUZ;?AG3gO5-0@aREC$`wi@ zBRo_&V0-NWQ~E3@vFv!7QUzutPEGNOxINvc!Jf{%;jp@;G-N}zms{Wum$qM2G^IIE P00000NkvXXu0mjf6QRm^ literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_3_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_3_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..0e87301ded85d699e1e518ad26dd0d96edc4d929 GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU{K&-V_;xdG`FsWfq@~=)5S3)F6vw|!8WSUZk!ESIqz_{eS(zf6XwlM@PMD5~SZJB98`}t-B4uuL1C`$sI5;>sI5;>sI9?nAfXCzUA{0dx0U#7biCDd2iTq31-_4a6 zfGhx{si~O-xLD zL~gt22XHhRjb4gGBA27l=rsUG7u&5?Yh^4J z``+Pjd>o6#E-w4_r=+AL0PJIA*Aj;0pHc%8*v~JzHtIso5DwR5lqVh8{ zGw;8Q5;$SCT7Lv^ftA(qcsvN8kgxzKWOY?EP5%wxyxDAS2JrRN)YJ_CCBb0uo>VH8 z(=>e_fO2MLMh~Fc@Ar>LrBXS=FctvHKplao^)iA1&tg+kSV0|(v)0F%iy<955NolfVOW5j3uCH2v4;=xBB_1M2GPWWiwY9)QE+fgU93P5eNh&;c(ck)oK-yNaTS^ zrIIJ-he9DoUtgah7K=UHwQHBsU@)8kpiaug_E0F~U>HUbjYg+cDwTZM^PjEb&8exW z41g`^>FHLrT3udQSy`71fJ&wMOry~hW@l#`0Bq**co6`5k~O|_=gtP5PFG%4RduAh zySuuqtn6EjMpIZ&P|)pmyUF0-AnESzCTg`h>5`buW@0oNNpEj2xqbUK>Fw<$O-)Tt z?UR#}WN2uJyo?^uU^bgu09-rwK<8pANQ^73+-&*!@X;PCO|$4O014H+97BaMxXWME)`==FL+2qAvI zpENWykj~Cd($&>Pv|24O8jVkbkVquR%en__W94RvL^48ARAF&(aeHzh`T6-bDT*qR z$z*o`l(8pA3Hwe+WxIH3MMcGl=H}+2?c2AX1^|&r?zPbJw4qA z;NAK8c@hqX34m>0ueTRKEt>&k$y;MGd$O{!?g7Y1Pfxc3*vRUa zm8G}|{?^melMCR6(P%7KSXj7jx7)v&pP&DgVHhwBgC|d(=*(vG`wI&T!vg~YTL5$o z4i07k_`_r}y#?T^&1S0&27?xh#nQ+yjP>r_yPp79_9N_H7m^q~JtUF800000NkvXX Hu0mjfY!a$b literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_4_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_4_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..a7e5ce8af155e65763cca386e00680b9290e1d65 GIT binary patch literal 150 zcmV;H0BQe;P)zW@a&KmlHXiT^7Wpa2DYUX-5&C#Cw5KL7v#07*qoM6N<$ Eg7S?tlmGw# literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_5.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_5.png new file mode 100644 index 0000000000000000000000000000000000000000..fc1e798b7c556753ff095b7a312ecdb82336d1e7 GIT binary patch literal 2214 zcmV;X2wC@uP)~qiKKIhI1%na{`)>w%JwJ9APU>LQrAzD&X!AE^kBUNfcP^roYLa9*E zU}KYhXf?5o*0i(|ZQ}#165@xdl~{wORzP_TFwES!_ndprW3PSyEiDNs)=!<^x3ja> z|KzN*{(J2W!wfUbFvAQp%rL_YGt4l<3^UCCJ#Nc&l4-tH{I;8A?3b6yXU%`Pr{_Mq zH2=7~e8+qNCb%OP%ET!vq&Q}Q*o7-3+i{~zKKEYHP2ZKm*xTjP=mQe~o|`%ICxHEV zzW2CfAwgLINgQ+NV0tQ=y?(C1(BOYArm5n|&d$XP_jrVjA*$6Kc>W{`*%tcu58!8A zqWXI$6(5YE-lsY{TUtGDAU5VsVAfc4)C#srweqHV+&noFfq(OjO*HF3PI!@R9q zdxIe0@W3GyE{?AWqXuCdV^TvDxhEC(wO)P2)~&boY}&MPXSMn`ko-?O!1c0ZbcsqW zB8tM#EVw5KT7#kLaqErxAV9yuMhR#=ilkv^#DkOy1(Mh%)ddJCe()s-m96&z>L zl{?Sj_mkdQ4)g-c0p`3tsdwX)f35&9BFl`(D%-NsdXg-wi#(jqWP&tFex#II_fw=-IUC#1_%H9`Rak5?#7hGUYDuS}&Gd$8}`lG-ZKz`Hg*((a|3k4Ya?97=D0A;`@KUaVz zplw4}*H3{GklozVvs@Lfm18!zBi<~``#8RJ~(+-YmQE=m%& zmL%W5b=MgnDJYv_p@qH!dr($}7pLuAzGG;pz2tc}9|*%=O)3<2SEA^ioNceZrT^lk zzZ~%r!19Y;pV<4`Dceaz9=4Sd-?o34h^(onsq5SJ4~#KuEx;(XM8O)Zl<~B_OC7Zj z&>N=dPaMmNPig_Xe5v@YS4qC(d*T)^7oELWa&5PYTfSc0@(l4t&K0|Pjx>+ESu)vf z(cag^DffumI#2Mr1hAi*Ide780Ze|OyL)B6eXiu&=ShCd0CTG888uO``!8HuLBA| z{?FartAWWt@fiD9FLZaW1pH4m1~m=_hj8daFb!fiMDt2bPa$ zmoyr}^+o`UuEcR3*b97ceP8$8QDg{e0g?z}^7z>%EDfb`w+m47v`&t;=@6DD{A6+l@>9 zK6zOj4kF=h3eBgJ;9{bGfF4PjhCDy5vb+*Sy_QmIT&?4bW!()dzwq_Zy`mJh(kPwf z=`**Hh^*@m!;){?H&&wP@iyN-h-EEKjagrGoSK29VUny%jj_tEdwVMK%a#X${D!VBGxyb3*8}-yX3PlYZrQT_Xjh)(B&bqs+agKoWNe2ds1i47 zbWAu6OJz|`gzHTttnR>eHFh=!5@L*l?Ro%l#zrkUz&n5r;@AVm0If$y zKpSw#x9tXy0!dcu25<<-p4g5HRPhCJDp$#& zV;>xAkZRpSk_f*z8Q&dA9M>^P10#k)u8nfBM7k?fqyg_^#s@8LSV0|ej= zn7^Aly>mK100Izz00bZa0YqIGLiYb9y`293T%#+{a|3Z$2Oy@&gz5kQ002ovPDHLk FV1hn^HM;-+ literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_6.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_6.png new file mode 100644 index 0000000000000000000000000000000000000000..6f9f7dcc0a676f9447f66504d6a52a9cf1a2cf00 GIT binary patch literal 683 zcmV;c0#yBpP)$gCF zFKO1%Q`G#Lln+Hk;96=s3SPs~&(!D2_xkwOq{vWFTmw5G6-iyyiA+RR(e5hWS9;!R z{uY?4_AHdvA#eq}0e-e!1D?s*fpRkerrOlhM0y1D7MP~pmKATV;TeCQZO_+~5yzUuk;ZiK@}0M{499=*3zA9ojniDCimFy?_{Yz;P)Y4(tHUUo_zX7RMs;Xod2Yz&ElhocxkAYqoknwyVof1myO?P$U6k8DrA2zppKn19w& z7Kp#wP&U85lru{HPZ+~Ge^XTt26e`e&>lVozopr01z8DQvd(} literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_7.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_7.png new file mode 100644 index 0000000000000000000000000000000000000000..844c09ac819c6da874b441b9bf11a4d561de0e15 GIT binary patch literal 960 zcmV;x13&zUP)D46d|SsFA@&5YK|Vf?z)xal6UcdTD0Nu;;@8$>xgvRm0Pp+0o4R?RyKP zq@<*zq@<*zq@<*zq@<(_Nu$wt@r(Nz0{{_i0ayTlr;o}Ez#eveX08FSwDC~f8}$Jc zi^ZNA7YcJWzIgHazqKA(4c{eRzzzquHInb(G0KZ>F%GuN2e z1>n7R3dm$KKi<#Yt4g`IWq85JjUkiC3@zEIsi{r14l}myihkN<5uEXYJE#7DN!lx|D%AByaYR) zPC;&@t;Z)PCu6m7X$uPg&d<-Y015zL7)AsDMs5s_vLdwKv9W@cvo zb{wbDYPJ4x9Oonq!z&BKaeQT^a=HBY)|(%#;jx&xCL1A3$`}AF)f@ppyCbYMAS75BiefWNwQH@fsCXR59y4QaZ|~#f<>fE${L1$C_uuMJc6WDg>{@nqcKDjPwk~_U z#%ukDo@48_y7NvD0G5`PGRfG=%1Y*@d8@0d*X0!S!|;87R#hA+dlNvr-|uIoP0r-^ ih$-isrk|)O@8&-YSS0W~hvoJF0000#d97y5kq{Oy2^P z0l53>XPp5)sPC@txQd&5@)j6>1`q%N5C8#;ybFBePY2I-V^fKvRDT4}>0d$tY`wi0 V4I13 zgVeC+p0&BxA6xr+k%=;S>)C3 zfI<=i@LizpD0x4@&4 zxu?DV|Afm;C&74@L4Fdnk~Kc914QJrs`iamt8-GI-6RFds=p7pipo|io%Qw8&{_kXTem$0%3I504> h2skuESbsTws+8fECbI%N-)A2Nkg2YIF6*2UngEY9{_2nJc?uh z5YfVizJ~lGHZ-B~b~fc1M3nqTkB#O5{In%nOY#!{d5FB-HWg;*0WcD+%3pehwYKn~ z3rHRNDtrvyh6kho2Fve^{hS-&=X4kQo)()6g|BQ4&L{T8h|Nu!jv)%%gkRT!L|&L3A8%pGr?P`r)UIEa#a@ok8abt zwv%Adu%X5^f)PwZ+3b02t>+c4k*a{S0ppo3R_1s`SmQpCN3Q~`HCe3;B=P`3Y zumP^lPc0u8lPQwpLjb_##V7j15w33@R_02)yuJYd_B)+l^so6G0C4yCOfd}*d=)Mx zQzyMY9N}qvU(3T4=Fiq#g{2(eic=}piRcVK<_LiSfZJ_of2CHnu8m!3lO;KAw7X6C Y2Ho!#AuAL337q$h{ zx9!bh%UHB;)4Yq#;^9xV1M1iW7#IZ{>go>2_3|k&FnQQBr|sJtfB#ARymQRcck`&q Sv-Zk@jP!K%b6Mw<&;$TggE-v) literal 0 HcmV?d00001 diff --git a/settingtypes.txt b/settingtypes.txt index 8d8291a0a..41fdb2458 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -66,6 +66,10 @@ mcl_showDeathMessages (Show death messages) bool true # If disabled, all recipes will be shown. mcl_craftguide_progressive_mode (Learn crafting recipes progressively) bool true +# If disabled, the skin of all players will be character.png +mcl_enable_skin_customization (Enable player skin customization) bool true + + [Mobs] # If enabled, mobs will spawn naturally. This does not affect # affect mob spawners. From 413c6292ff96802a97f963121c353ef7d9b4b438 Mon Sep 17 00:00:00 2001 From: Johannes Fritz Date: Tue, 6 Sep 2022 12:51:43 -0500 Subject: [PATCH 2/2] Add simple skins skins support --- mods/ITEMS/mcl_maps/init.lua | 33 ++- mods/PLAYER/mcl_meshhand/init.lua | 36 ++-- mods/PLAYER/mcl_skins/LICENSE.txt | 1 + mods/PLAYER/mcl_skins/README.md | 21 +- mods/PLAYER/mcl_skins/edit_skin.lua | 197 ++++++++++++------ mods/PLAYER/mcl_skins/init.lua | 6 +- mods/PLAYER/mcl_skins/list.json | 3 +- mods/PLAYER/mcl_skins/locale/template.txt | 1 + mods/PLAYER/mcl_skins/mesh_hand.lua | 53 +++++ mods/PLAYER/mcl_skins/simple_skins.lua | 52 +++++ .../textures/mcl_skins_select_overlay.png | Bin 167 -> 178 bytes 11 files changed, 292 insertions(+), 111 deletions(-) create mode 100644 mods/PLAYER/mcl_skins/mesh_hand.lua create mode 100644 mods/PLAYER/mcl_skins/simple_skins.lua diff --git a/mods/ITEMS/mcl_maps/init.lua b/mods/ITEMS/mcl_maps/init.lua index 6fae7c13d..09dcd4f95 100644 --- a/mods/ITEMS/mcl_maps/init.lua +++ b/mods/ITEMS/mcl_maps/init.lua @@ -231,31 +231,22 @@ filled_wield_def._mcl_wieldview_item = "mcl_maps:filled_map" 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 - local bases = mcl_skins.base - local base_colors = mcl_skins.base_color - -- Generate a node for every skin - for _, base in pairs(bases) do - for _, base_color in pairs(base_colors) do - local node_id = player_base_to_node_id(base, base_color, "male") - 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 list = mcl_skins.get_skin_list() + for _, skin in pairs(list) do + if skin.slim_arms then 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.tiles = {texture} - minetest.register_node("mcl_maps:filled_map_" .. node_id, female) + female.tiles = {skin.texture} + 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 else diff --git a/mods/PLAYER/mcl_meshhand/init.lua b/mods/PLAYER/mcl_meshhand/init.lua index 03335710f..96086e4f2 100644 --- a/mods/PLAYER/mcl_meshhand/init.lua +++ b/mods/PLAYER/mcl_meshhand/init.lua @@ -21,31 +21,22 @@ local node_def = { 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 - local bases = mcl_skins.base - local base_colors = mcl_skins.base_color - -- Generate a node for every skin - for _, base in pairs(bases) do - for _, base_color in pairs(base_colors) do - local node_id = player_base_to_node_id(base, base_color, "male") - 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 list = mcl_skins.get_skin_list() + for _, skin in pairs(list) do + if skin.slim_arms then 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.tiles = {texture} - minetest.register_node("mcl_meshhand:" .. node_id, female) + female.tiles = {skin.texture} + 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 else @@ -58,8 +49,7 @@ end if mcl_skins_enabled then -- Change the player's hand to their skin mcl_skins.register_on_set_skin(function(player) - local data = mcl_skins.players[player:get_player_name()] - local node_id = player_base_to_node_id(data.base, data.base_color, data.slim_arms and "female" or "male") + local node_id = mcl_skins.get_node_id_by_player(player) player:get_inventory():set_stack("hand", 1, "mcl_meshhand:" .. node_id) end) else diff --git a/mods/PLAYER/mcl_skins/LICENSE.txt b/mods/PLAYER/mcl_skins/LICENSE.txt index 14ffbdee0..da582622b 100644 --- a/mods/PLAYER/mcl_skins/LICENSE.txt +++ b/mods/PLAYER/mcl_skins/LICENSE.txt @@ -1,6 +1,7 @@ The MIT License (MIT) Copyright (c) 2022 MrRar +Copyright (c) 2016 TenPlus1 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/mods/PLAYER/mcl_skins/README.md b/mods/PLAYER/mcl_skins/README.md index bc9924af9..a6ad02f30 100644 --- a/mods/PLAYER/mcl_skins/README.md +++ b/mods/PLAYER/mcl_skins/README.md @@ -1,11 +1,11 @@ -# mcl_skins +# Mineclone Skins This mod allows advanced skin customization. Use the /skin command to open the skin configuration screen. ## License Code under MIT license -Author: MrRar +Author: TenPlus1, Zeg9, MrRar 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. The function will be given a player ObjectRef as a parameter. -### `mcl_skins.make_hand_texture(base, colorspec)` -Generate a texture string from a base texture and color. -This function is used by mods that want to have a first person hand textured like the player skin. +### `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. +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)` 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. ### `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. ### mcl_skins.compile_skin(skin) diff --git a/mods/PLAYER/mcl_skins/edit_skin.lua b/mods/PLAYER/mcl_skins/edit_skin.lua index b650a645f..eea6e5e87 100644 --- a/mods/PLAYER/mcl_skins/edit_skin.lua +++ b/mods/PLAYER/mcl_skins/edit_skin.lua @@ -2,6 +2,7 @@ local S = minetest.get_translator("mcl_skins") local color_to_string = minetest.colorspec_to_colorstring mcl_skins = { + simple_skins = {}, item_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"}, tab_names = {"template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"}, tab_descriptions = { @@ -14,7 +15,8 @@ mcl_skins = { bottom = S("Bottoms"), top = S("Tops"), hair = S("Hairs"), - headwear = S("Headwears") + headwear = S("Headwears"), + skin = S("Skins"), }, steve = {}, -- Stores skin values for Steve skin alex = {}, -- Stores skin values for Alex skin @@ -70,10 +72,13 @@ function mcl_skins.register_item(item) end function mcl_skins.save(player) - local name = player:get_player_name() - local skin = mcl_skins.players[name] + local skin = mcl_skins.players[player] 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 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 }) -function mcl_skins.make_hand_texture(base, colorspec) - local output = "" - if mcl_skins.masks[base] then - 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 - function mcl_skins.compile_skin(skin) + if skin.simple_skins_id then + return mcl_skins.simple_skins[skin.simple_skins_id].texture + end + local output = "" - for i, tab in pairs(mcl_skins.item_names) do - local texture = skin[tab] + for i, item in pairs(mcl_skins.item_names) do + local texture = skin[item] 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 - local color = color_to_string(skin[tab .. "_color"]) + local color = color_to_string(skin[item .. "_color"]) output = output .. "(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)" end @@ -117,11 +115,17 @@ function mcl_skins.update_player_skin(player) return 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)) - 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_inventory.update_inventory_formspec(player) @@ -136,30 +140,34 @@ minetest.register_on_joinplayer(function(player) local function table_get_random(t) return t[math.random(#t)] end - local name = player:get_player_name() local skin = player:get_meta():get_string("mcl_skins:skin") if skin then skin = minetest.deserialize(skin) end if skin then - mcl_skins.players[name] = skin + mcl_skins.players[player] = skin else if math.random() > 0.5 then skin = table.copy(mcl_skins.steve) else skin = table.copy(mcl_skins.alex) 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 mcl_skins.save(player) mcl_skins.update_player_skin(player) end) minetest.register_on_leaveplayer(function(player) - local name = player:get_player_name() - if name then - mcl_skins.players[name] = nil - end + mcl_skins.players[player] = nil end) mcl_skins.registered_on_set_skins = {} @@ -169,7 +177,9 @@ function mcl_skins.register_on_set_skin(func) end 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 local page_count @@ -179,13 +189,16 @@ function mcl_skins.show_formspec(player, active_tab, page_num) 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 player_name = player:get_player_name() - local skin = mcl_skins.players[player_name] local formspec = "formspec_version[3]size[13.2,11]" 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 formspec = formspec .. "button[0.3," .. y .. ";3,0.8;" .. tab .. ";" .. mcl_skins.tab_descriptions[tab] .. "]" + + if skin.simple_skins_id then break 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 .. "model[10,0.3;3,7;player_mesh;" .. mesh .. ";" .. mcl_skins.compile_skin(skin) .. ",blank.png,blank.png;0,180;false;true;0,0;0]" - - if active_tab == "template" then + 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]" + + 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 .. "model[4,2;2,3;player_mesh;mcl_armor_character.b3d;" .. 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 formspec = formspec .. - "style_type[button;border=false;bgcolor=#00000000]" + "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) @@ -264,19 +326,19 @@ function mcl_skins.show_formspec(player, active_tab, page_num) if skin[active_tab] == texture then formspec = formspec .. - "style[" .. texture .. ";border=false;bgcolor=#00000000]" .. - "image_button[" .. x .. "," .. y .. - ";1.5,1.5;mcl_skins_select_overlay.png;" .. texture .. ";]" - else - formspec = formspec .. "button[" .. x .. "," .. y .. ";1.5,1.5;" .. texture .. ";]" + "style[" .. texture .. + ";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,1.5;" .. texture .. ";]" end elseif active_tab == "arm" then - local thick_overlay = not skin.slim_arms and "^mcl_skins_select_overlay.png" or "" - local slim_overlay = skin.slim_arms and "^mcl_skins_select_overlay.png" or "" + local x = skin.slim_arms and 4.7 or 3.6 formspec = formspec .. - "image_button[3.6,0.3;1,1;mcl_skins_thick_arms.png" .. thick_overlay ..";thick_arms;]" .. - "image_button[4.7,0.3;1,1;mcl_skins_slim_arms.png" .. slim_overlay ..";slim_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_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 @@ -287,11 +349,6 @@ function mcl_skins.show_formspec(player, active_tab, page_num) local tab_color = active_tab .. "_color" local selected_color = skin[tab_color] 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) i = i - 1 local x = 3.6 + i % 6 * 0.9 @@ -299,7 +356,15 @@ function mcl_skins.show_formspec(player, active_tab, page_num) formspec = formspec .. "image_button[" .. x .. "," .. y .. ";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 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 .. "]" end + local player_name = player:get_player_name() minetest.show_formspec(player_name, "mcl_skins:" .. active_tab .. "_" .. page_num, formspec) 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 page_num = math.floor(tonumber(page_num) or 1) - local player_name = player:get_player_name() - -- Cancel formspec resend after scrollbar move - if mcl_skins.players[player_name].form_send_job then - mcl_skins.players[player_name].form_send_job:cancel() + if mcl_skins.players[player].form_send_job then + mcl_skins.players[player].form_send_job:cancel() end if fields.quit then @@ -380,12 +444,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end 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.show_formspec(player, active_tab, page_num) return true 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.show_formspec(player, active_tab, page_num) return true @@ -398,7 +462,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end end - local skin = mcl_skins.players[player_name] + local skin = mcl_skins.players[player] if not skin then return true end 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 if color >= 0 and color <= 0xffffffff then -- 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 skin[active_tab .. "_color"] = color mcl_skins.update_player_skin(player) 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) return true @@ -459,6 +523,21 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) 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 if field and mcl_skins[active_tab] then for i, texture in pairs(mcl_skins[active_tab]) do diff --git a/mods/PLAYER/mcl_skins/init.lua b/mods/PLAYER/mcl_skins/init.lua index 869e008d4..f1192ba16 100644 --- a/mods/PLAYER/mcl_skins/init.lua +++ b/mods/PLAYER/mcl_skins/init.lua @@ -1,4 +1,8 @@ local mod_path = minetest.get_modpath(minetest.get_current_modname()) 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 diff --git a/mods/PLAYER/mcl_skins/list.json b/mods/PLAYER/mcl_skins/list.json index e31c38066..163111a4c 100644 --- a/mods/PLAYER/mcl_skins/list.json +++ b/mods/PLAYER/mcl_skins/list.json @@ -173,7 +173,8 @@ }, { "type": "headwear", - "steve": true + "steve": true, + "alex": true }, { "type": "bottom", diff --git a/mods/PLAYER/mcl_skins/locale/template.txt b/mods/PLAYER/mcl_skins/locale/template.txt index 1facf03d5..12ba740d5 100644 --- a/mods/PLAYER/mcl_skins/locale/template.txt +++ b/mods/PLAYER/mcl_skins/locale/template.txt @@ -1,4 +1,5 @@ # textdomain: mcl_skins +Skins= Templates= Arm size= Bases= diff --git a/mods/PLAYER/mcl_skins/mesh_hand.lua b/mods/PLAYER/mcl_skins/mesh_hand.lua new file mode 100644 index 000000000..8bbcff878 --- /dev/null +++ b/mods/PLAYER/mcl_skins/mesh_hand.lua @@ -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 diff --git a/mods/PLAYER/mcl_skins/simple_skins.lua b/mods/PLAYER/mcl_skins/simple_skins.lua new file mode 100644 index 000000000..523832f30 --- /dev/null +++ b/mods/PLAYER/mcl_skins/simple_skins.lua @@ -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() diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_select_overlay.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_select_overlay.png index dabc824bfc948a75d555afa7c484b3fd994561a6..93e6567032f94768dec667de55a0ada1141d543a 100644 GIT binary patch delta 150 zcmV;H0BQfH0kQ#*B!78HL_t(o!|hi=4!|G?Yt8=uWxXxN1EM35ZSBpNKxr%j0aWaP z!+9%C!C_oC{pu@#qE@0KolwPVUm44gw9U63i}i8?vI2XHWTzW8g5y4e+(0Y|?cIA%qY@h`&U#5tW8= t2UAnA+>*H5Q%+ZV&{0lTzo5OIUtV$`8TN1U3IG5A07*qoL