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!ia0vp^0wB!61|;P_|4#%`0iG_7Ar_~T6C`pT*oz4B&M@%# z@qfNbvxMPSpa_cJxAK(iSW|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*dNKNg1r~|FS?yf7@yE&->sFs1@z>_Dfmi3F-WWhWJhA%S?{(f+F`uFCn qS}O*IhPd4a*6(i9he`segbX=_qinYBGuVOB3=E#GelF{r5}E*v!Y=Iq 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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQsJI1jv*QM-d<1SYEa;5xcKz% z`#pLB8eUs&RNE`7*v*Mx0V=w1_Ui{7@q3mNrSE^4b+MM6;{nf%^C=;-BCQ=57+C~> qgx6i>eLvzgw^sbKY%pF>-5{Mei&gfR+Kp78ZU#?RKbLh*2~7Z*6EPD2 literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_2.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_2.png new file mode 100644 index 0000000000000000000000000000000000000000..3053b422b822c0365fefced4fad6a0e076d8350c GIT binary patch literal 694 zcmV;n0!jUeP)FMPtl(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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQgNOxjv*QM-d+#nYETehJ)pbm z|J3c=EX!1NEkA44ok*Ua!2(pZVb4^S8F&08W>m< z7#KMgT(N%8{lAN|;`GIdCI7ZEZQj3qsdfRA#{o9^ubu6yfMzgwy85}Sb4q9e0P!3( A;Q#;t literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_3.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_bottom_3.png new file mode 100644 index 0000000000000000000000000000000000000000..aacfeb334f40795337a4cd6d96c1012657a88941 GIT binary patch literal 604 zcmV-i0;BzjP)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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQURVWjv*QM-d;b+$)Lc)avl%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=+ O0000bP0l+XkK7$Yo) 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 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 DKOkQJ diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_eye_1.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_eye_1.png new file mode 100644 index 0000000000000000000000000000000000000000..ff19a09b3e90a61ac32becfd99dfad3f38dc7423 GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQbnFFjv*QM-d^3v*8}(BoGM_Wd`yYGiNs$Z#!-3hgeQRzOJvWX1X8CD00P9FqJVPhwJm& Rzbf}ZTu)a&mvv4FO#p6RDLViF 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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQvRMUjv*QM-d?cgY6uWuK9Kv@ z>=Cc+-W3V|6LPQkRTr`aE%8xeU}zApR8vxVwd>Tj+)w6@kFR{P@7(tXtH0NN?-y>% jJz1#r^9m!-um{$BZpyN=Bz?l40eK9bu6{1-oD!Mn;X56ym;w|?j9B9JbIeZ>qMC%EsfS-Q9b#PxLbb6Mw<&;$Uo C+aGuU 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!ia0vp^4nVBH!3HE3&8=$zQgNOxjv*QM-d8iqV-jVuB~nB%j;) v{oZ=ju&$0(tKObnbxUc{CwZVM5UBsmQ1qLBU9rlOSP<9K)z4*}Q$iB}!Gbs2 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!ia0vp^4nVBH!3HE3&8=$zQd*uajv*QM-d@U{wba!tOpP>x z^h`1w?5l%3^;KL=jGgRkq8$yh{cL@`+#@|)tKvKhW5c5}Cg)c#^=ON4$_U<6o-?yG z`(S_l#idhjZ=U;V#pYKhw;ex!FVdQ&MBb@0O==E AYXATM 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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQfoY2978hhy}fSBcgTQ;^}+KF zAD)}aM>MPY=P~oSoWFRl+1iCC<=ughm1&%Ts%;8t9{09e*vBPRb}%YIKvwS*pV zo~N=hSY#XAlM4!FEL+-A8ToL{$=A0;xF4)JxQ%(1w!>Rl2NxHYEAI?S7{4s(3S{|S z@*?=oyXsILrTp*D`Po*@|HtL7V6U_6@L`jK)&1GmpB`~kxxfF2RFp%gY0HB9$Lj0< a3*Y>dy6nNvw_-qdGkCiCxvX!*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)@+500000vojxB*C+9rJkUS?Os{ggwS#_l zsFFnJZ&SI0ho)q-TbVp~{dCDI_k^Xp=G7=pv*4S_`Rm!b>gm^jmN76i+)^tGV%IPB RWC;dwJzf1=);T3K0RRD@J!t>{ 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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQWHI0978hhy`AnYbU=Z_x%2Vg z^>gAD+z-_8xVLI`UoFdq4e1%l2beCeu@DM~b(sG}&f;vp2xmi-1JkEv%#6RjtW~Kx z@s=~l>wL=B#w^2%q-EO~=3Kk8zIf4H87}qn(Q6NAGyeF|xQjhynt?aNX0C`(%XcQ` z+q}B|v1*0Kb53X|Wm>_)65IGRdchZ22M$G-Qa-;-KI=6~hZh4K$KdJe=d#Wzp$P!< CNlefH literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_1_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_1_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..cc58ddd23e11ba2003379366323d7cd864403a6f GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQr(^|jv*QM-cI-CV^HL9Uit7} zc$%NVe3z3B6?bD-KUTX~4q3 tuwV_Nn%p%Dpg}W&|1T|OU{^4S7C)RIV$#n1=N?d$!PC{xWt~$(69C_DMLPfh literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_2.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_2.png new file mode 100644 index 0000000000000000000000000000000000000000..d0f4a24e4be70bafcf0c89d47ffd2ac06db67020 GIT binary patch literal 490 zcmV}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!ia0vp^4nVBH!3HE3&8=$zQU#tajv*QM-d@e+Vo>C84UFIM zU)Ne%;+I2)+n(q70^f`#uRWR+8+K#EGmZuZ5L#fI`{%QH){h?b?w(h&4^G|={Hk#5 zbmNqq^iaM9vhiE0ecGPpG^{$c*+Mq&R*e1K_tWD8WY`p#fp#%4XgpvvUBjypDI9nL O#PxLbb6Mw<&;$Ury*zmU literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_3.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_3.png new file mode 100644 index 0000000000000000000000000000000000000000..d88945b414c2a11f044d1dcac8942aa4be18d909 GIT binary patch literal 445 zcmV;u0Yd(XP)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 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 P00000NkvXXu0mjf>j~PvG<6Bz%wh4FSr=IE5SfhR3cb7R#+uHJE@&$%FjM1CVJDC5uB-!Us$bLzZK~$$sh+*ocSVJbBd4Aa$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{5ujv*QM-d;5nYB1n%3B303 zU-+?WeCZw`PxhPnMlel$s$@CcwCqL!ivt4)8O+T4^V$E-L({lDDJAucac}x|u^ZO0 z|5&s$=eN)vgZIB)1l=`aD%3Q1z3ra?Q)HkK&<+NMhGl*Vo}BtJn-0teaXnrAT-G@y GGywp8r8tfN literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_7.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_7.png new file mode 100644 index 0000000000000000000000000000000000000000..2449a06ce03f770d01e62340746ab79231d99037 GIT binary patch literal 576 zcmV-G0>Ax4qH5PdJrr6Pjjt>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 O0000T&(AU{*etu;^d>g%zY6!7!?U;QB*SKQ@zMhpsaVc$pTYY5TDr&}{5|*THw- vWWy2$w|VE|ChoKEIkZ^7>#yCyj$I4~-tf53+qyRs=qd(JS3j3^P60w85Qd*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!ia0vp^4nVBH!3HE3&8=$zQpKJwjv*QM-d=O$YB1noy;$?{ zUwGf`pd)QMOFW-9N|#>b37fk1=c8R~Hk{^jXJ8U&U|_MB$#nmx{k08Wg%{-6+t1Wp zkeIP|PPXWSYy(#1sk{qbRa^ZQ>e0C++*~z1VV+FhzIvN&1?tW#eqRGx2L!dY^KS8| TpL%>@GKlBt>gTe~DWM4f{f|IH literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_9.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_9.png new file mode 100644 index 0000000000000000000000000000000000000000..dfbe0b574e888d3ec7dca3be90cdd2b9904c5232 GIT binary patch literal 730 zcmV<00ww*4P)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!ia0vp^4nVBH!3-p)I`?g3U|?nl@Ck7Ra^>U{wba!tOpP>x z^h`1w?5l%3^;KL=jGgRkq8$yh{cL@`+#@|)tKvKhW5c5}Cg)c#^=ON4$_U<6o-?yG z`(S_l#idhjZ=U;V#pYKhw;ex!WXh{y5d1PRu~4Jr!C&I=hYO_5Ykw!I(+6iE>2X%b{$xPFA;eu87DD9DSRu6{1- HoD!M<`!zv- literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_3.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_3.png new file mode 100644 index 0000000000000000000000000000000000000000..682eb4df4ce878c3fce2ecfe5c6286072e9484e8 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQudxMjv*QM-d-}~14^(M{P@4P z(40@rA|uCrS+g<|1H-;4)1R(%-FEKHO6Dt5mP@5xdzbg~z;wB6X`p5XB{mLgPL|k2 Q)gK_9r>mdKI;Vst0I~@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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQZAk@jv*QM-d?cgV^HK^b=doV z;ryw+o%_$7Jy+5%z%+%4fnk4${B8Bgca5%WdQtgt-RsBI=K|(G%}J}h_f8OK07JnF YMmzopr03{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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQo)`sjv*QM-d;B3Jz&7Y;?V9~ zIK?+$nr}gi^R6vHj1?JAcAxC7-|$C}f#J{fH_54KDNk}sTguD7ZQNJv;+#ZU mn@n$QV!HWNvz!HJAcLH_W533&=;UROKs--ZKbLh*2~7Z2J2K}0 literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_7.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_headwear_7.png new file mode 100644 index 0000000000000000000000000000000000000000..755b82a84540afa5840bab1eaed3989e068244c9 GIT binary patch literal 291 zcmV+;0o?wHP)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&7KZ=; 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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQjVT3jv*QM-d-}~J)j`saL`_0 zo7X{ZW3yFUwK+N=Oo>Z&7Jrx|&InW)z4z*+=-B#~p6wsA&q(^8TQ3R}Y>2Mqkl>ud Td{k-{kjLQZ>gTe~DWM4f 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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQbC?Bjv*QM-d@_s>kz=ea$$1E zIjwIOA`Tc$+t_eSF6`ppwqp!aD%S6Qvg))dQ28JK((M-fe4{m4u&`)e!XEB3pZ nC$~+Xv@KKZJ|j@Uy;m%TCpmBA`W`z6iB 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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQXZZzjv*QM-d^6w+2A1Ha#8!R z+ME4irZ=ASu!{5bT;n_Q^xo?S{65)0r8QA$eev#Tu1A7Huivcp-F{$W{`V6)?m!ua afA3hWR*0?Q%fI^?#PxLbb6Mw<&;$St8!b8j 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!ia0vp^4nVBH!3HE3&8=$zQfi(qjv*QM-d@^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!ia0vp^4nVBH!3HE3&8=$zQktGFjv*QM-d=FzWnkc7QBaOg tTAjiCKTn`h3n*(*YBaZp6Ub;dE+$mOT3uSy3slCy;OXk;vd$@?2>=Cz7hC`U literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_select_overlay.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_select_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..dabc824bfc948a75d555afa7c484b3fd994561a6 GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJJWm(Lkch)?r*9NGpupiQ-2eZ7 z>aH7nYh}6<+V@;l6#S^C$l%Viu|420!-2ome(x^L<747oEp$e&M0(SriRu17dy*d* z9OwP8bz#n>QVzuy0jG}rE}I0WwiU4l2XDMHX~&&lzwqh{fqvop7wnxEA6KLx`7Qr5 P$Vm*Iu6{1-oD!MKQy;{an^LB{Ts5R4*I{ 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!ia0vp^0wB!61|;P_|4#%`DxNNmAr_~T6C^SYbU6R9-}q{# rM(M#7j4KxYnlH0=aifI}4+F!}^Gwni1&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+L0000_{7nYG3D{{3a;I3Pda{?Ci$TbP&x8W>m<7;F`mG2i{a eQf>p6oAu{*R_W3+?^XacF?hQAxvX}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)E0000P_QwqKp`c%~3g$${F^f}GBpUs;?5RSh#Lo;_apS$_AshF?!luh-;`XDM%B tVB$~!5^w$s&-tp~VbAu0_v5WSdfPoYCDoRdCjw1i@O1TaS?83{1OVw_HMjr( literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_3.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_3.png new file mode 100644 index 0000000000000000000000000000000000000000..14b65d09a8c8dd4b0dde4e4d5f47dc649fbf9b84 GIT binary patch literal 941 zcmV;e15*5nP)OZAC3Eid%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!ia0vp^4nVBH!3HE3&8=$zQh}Z>jv*QM-d=CyWf0(Da9r|x zeT?^t3HNvdYFv_dfC?7Ojx;dtzJ6x%=dkb68}#mM_*vATF>k)?y@o$Od+sqXvIsbU iiH3ELnr)}mEi*g6fkid{$igb1UItHBKbLh*2~7Y;0WX9A literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_4.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_4.png new file mode 100644 index 0000000000000000000000000000000000000000..693ef3216d4ca6f94a0e3db940071f2c7fee16f2 GIT binary patch literal 1453 zcmV;e1ycHnP)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 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQn8*cjv*QM-d;b*dBA{&`G7^q z|EYJ~#ZN5eW4q70AV5)Qml#l$fv-qP+Q*qc)9>vIC@6_Luy4z{84(9&SS#><+WgwQ zFaALAocVXTCH6D0YB(^)HFo~j7F)o;S`#;AKCAlDUz6;CMlg7~`njxgN@xNA@{Kf< 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)u8nfBM7D9gimQyQcRo5}2l;#spMl;hVYU>5+L8-^@API&0sW_YbZ1GP6A3ow0wm_1
jA1_l-d21b`y38!!WRrk*M_b+C#_Jv~R!U%SSWhYx+0nK3WboFyt=akR{06u~> Ay8r+H 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;5ujv*QM-d=0uJ)pqD>?pMH z|0YR=yNp+_Wc_1fNEAFA1ysbqkT6SN&CN%)zt4XCcC_I3N46(l1U;-A%s=ZX3&h`T zD4Snj${8j9CyZg8zp1JRgF0hKXb+!)@%Q^o0soja9K8ho$^GHuVTn4h;S$I+Pgg&e IbxsLQ01z8DQvd(} 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~hvoJF0000ZWl6daR z-}s+%WM-E%cpduR%O|jY+YJt&G6n{NUaqWNJC+;2Ufca}*JJSyKKGfXGVb{ODt#`a z-HP|?-tXv|UHwT+qMl8Fff0y$_Hfrc_Gdp|mK@x zgVeC+p0&BxA6xr+k%=;S>)C3 zfI<=i@LizpD0x4@&4 zxu?DV|Afm;C&74@L4Fdnk~Kc914QJrs`iamt8-GI-6RFds=6y}E>zMZkf95lA#dSbsTw as+8fECbI%N-)A474hBzGKbLh*2~7Z;MJ3Vz literal 0 HcmV?d00001 diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_top_9.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_top_9.png new file mode 100644 index 0000000000000000000000000000000000000000..2b65eca986df80c2728eca825bf9062f02dd61dc GIT binary patch literal 482 zcmV<80UiE{P)Y9{_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!#AuAL 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