Merge pull request 'Add advanced skin customization' (#2607) from skins into master

Reviewed-on: MineClone2/MineClone2#2607
Reviewed-by: cora <cora@noreply.git.minetest.land>
This commit is contained in:
cora 2022-09-07 00:38:33 +00:00
commit 28417a91bf
111 changed files with 1731 additions and 567 deletions

View File

@ -364,7 +364,8 @@ function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size,
-- Survival inventory slots -- Survival inventory slots
main_list = "list[current_player;main;0,3.75;9,3;9]" .. main_list = "list[current_player;main;0,3.75;9,3;9]" ..
mcl_formspec.get_itemslot_bg(0, 3.75, 9, 3) .. mcl_formspec.get_itemslot_bg(0, 3.75, 9, 3) ..
-- armor
-- Armor
"list[current_player;armor;2.5,1.3;1,1;1]" .. "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;2.5,2.75;1,1;2]" ..
"list[current_player;armor;5.5,1.3;1,1;3]" .. "list[current_player;armor;5.5,1.3;1,1;3]" ..
@ -376,26 +377,35 @@ function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size,
"list[current_player;offhand;1.5,2.025;1,1]" .. "list[current_player;offhand;1.5,2.025;1,1]" ..
mcl_formspec.get_itemslot_bg(1.5, 2.025, 1, 1) .. mcl_formspec.get_itemslot_bg(1.5, 2.025, 1, 1) ..
armor_slot_imgs .. armor_slot_imgs ..
-- player preview
-- Player preview
mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "") .. mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "") ..
-- crafting guide button
-- Crafting guide button
"image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]" .. "image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]" ..
"tooltip[__mcl_craftguide;"..F(S("Recipe book")) .. "]" .. "tooltip[__mcl_craftguide;"..F(S("Recipe book")) .. "]" ..
-- help button
-- Help button
"image_button[9,2;1,1;doc_button_icon_lores.png;__mcl_doc;]" .. "image_button[9,2;1,1;doc_button_icon_lores.png;__mcl_doc;]" ..
"tooltip[__mcl_doc;" .. F(S("Help")) .. "]" .. "tooltip[__mcl_doc;" .. F(S("Help")) .. "]" ..
-- skins button
"image_button[9,3;1,1;mcl_skins_button.png;__mcl_skins;]".. -- Achievements button
"tooltip[__mcl_skins;"..F(S("Select player skin")).."]".. "image_button[9,3;1,1;mcl_achievements_button.png;__mcl_achievements;]" ..
-- achievements button
"image_button[9,4;1,1;mcl_achievements_button.png;__mcl_achievements;]"..
--"style_type[image_button;border=;bgimg=;bgimg_pressed=]" .. --"style_type[image_button;border=;bgimg=;bgimg_pressed=]" ..
"tooltip[__mcl_achievements;"..F(S("Achievements")) .. "]" .. "tooltip[__mcl_achievements;"..F(S("Achievements")) .. "]" ..
-- switch stack size button
"image_button[9,5;1,1;default_apple.png;__switch_stack;]".. -- Switch stack size button
"label[9.4,5.4;".. F(C("#FFFFFF", stack_size ~= 1 and stack_size or "")) .."]".. "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")) .. "]" "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 -- For shortcuts
listrings = listrings .. listrings = listrings ..
"listring[detached:"..playername.."_armor;armor]".. "listring[detached:"..playername.."_armor;armor]"..

View File

@ -75,7 +75,8 @@ local function set_inventory(player, armor_change_only)
local form = "size[9,8.75]" .. local form = "size[9,8.75]" ..
"background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png]" .. "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, "") .. mcl_player.get_player_formspec_model(player, 1.0, 0.0, 2.25, 4.5, "") ..
--armor
-- Armor
"list[current_player;armor;0,0;1,1;1]" .. "list[current_player;armor;0,0;1,1;1]" ..
"list[current_player;armor;0,1;1,1;2]" .. "list[current_player;armor;0,1;1,1;2]" ..
"list[current_player;armor;0,2;1,1;3]" .. "list[current_player;armor;0,2;1,1;3]" ..
@ -87,7 +88,8 @@ local function set_inventory(player, armor_change_only)
"list[current_player;offhand;3,2;1,1]" .. "list[current_player;offhand;3,2;1,1]" ..
mcl_formspec.get_itemslot_bg(3,2,1,1) .. mcl_formspec.get_itemslot_bg(3,2,1,1) ..
armor_slot_imgs .. armor_slot_imgs ..
-- craft and inventory
-- Craft and inventory
"label[0,4;"..F(minetest.colorize("#313131", S("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,4.5;9,3;9]" ..
"list[current_player;main;0,7.74;9,1;]" .. "list[current_player;main;0,7.74;9,1;]" ..
@ -98,24 +100,34 @@ local function set_inventory(player, armor_change_only)
mcl_formspec.get_itemslot_bg(0, 7.74, 9, 1) .. mcl_formspec.get_itemslot_bg(0, 7.74, 9, 1) ..
mcl_formspec.get_itemslot_bg(4, 1,2, 2) .. mcl_formspec.get_itemslot_bg(4, 1,2, 2) ..
mcl_formspec.get_itemslot_bg(7, 1.5, 1, 1) .. mcl_formspec.get_itemslot_bg(7, 1.5, 1, 1) ..
-- crafting guide button
-- Crafting guide button
"image_button[4.5,3;1,1;craftguide_book.png;__mcl_craftguide;]" .. "image_button[4.5,3;1,1;craftguide_book.png;__mcl_craftguide;]" ..
"tooltip[__mcl_craftguide;"..F(S("Recipe book")) .. "]" .. "tooltip[__mcl_craftguide;"..F(S("Recipe book")) .. "]" ..
-- help button
-- Help button
"image_button[8,3;1,1;doc_button_icon_lores.png;__mcl_doc;]" .. "image_button[8,3;1,1;doc_button_icon_lores.png;__mcl_doc;]" ..
"tooltip[__mcl_doc;"..F(S("Help")).."]".. "tooltip[__mcl_doc;" .. F(S("Help")) .. "]"
-- skins button
-- Skins button
if minetest.global_exists("mcl_skins") then
form = form ..
"image_button[3,3;1,1;mcl_skins_button.png;__mcl_skins;]" .. "image_button[3,3;1,1;mcl_skins_button.png;__mcl_skins;]" ..
"tooltip[__mcl_skins;"..F(S("Select player skin")).."]".. "tooltip[__mcl_skins;" .. F(S("Select player skin")) .. "]"
-- achievements button end
form = form ..
-- Achievements button
"image_button[7,3;1,1;mcl_achievements_button.png;__mcl_achievements;]" .. "image_button[7,3;1,1;mcl_achievements_button.png;__mcl_achievements;]" ..
"tooltip[__mcl_achievements;" .. F(S("Achievements")) .. "]" .. "tooltip[__mcl_achievements;" .. F(S("Achievements")) .. "]" ..
-- for shortcuts
-- For shortcuts
"listring[current_player;main]" .. "listring[current_player;main]" ..
"listring[current_player;armor]" .. "listring[current_player;armor]" ..
"listring[current_player;main]" .. "listring[current_player;main]" ..
"listring[current_player;craft]" .. "listring[current_player;craft]" ..
"listring[current_player;main]" "listring[current_player;main]"
player:set_inventory_formspec(form) player:set_inventory_formspec(form)
end end

View File

@ -229,17 +229,31 @@ filled_wield_def.range = minetest.registered_items[""].range
filled_wield_def.on_place = mcl_util.call_on_rightclick filled_wield_def.on_place = mcl_util.call_on_rightclick
filled_wield_def._mcl_wieldview_item = "mcl_maps:filled_map" filled_wield_def._mcl_wieldview_item = "mcl_maps:filled_map"
for _, texture in pairs(mcl_skins.list) do local mcl_skins_enabled = minetest.global_exists("mcl_skins")
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 female_def = table.copy(def) if mcl_skins_enabled then
female_def.mesh = "mcl_meshhand_female.b3d" -- Generate a node for every skin
female_def._mcl_hand_id = texture .. "_female" local list = mcl_skins.get_skin_list()
minetest.register_node("mcl_maps:filled_map_" .. texture .. "_female", female_def) for _, skin in pairs(list) do
if skin.slim_arms then
local female = table.copy(filled_wield_def)
female._mcl_hand_id = skin.id
female.mesh = "mcl_meshhand_female.b3d"
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
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 end
local old_add_item = minetest.add_item local old_add_item = minetest.add_item

View File

@ -1,76 +1,56 @@
local has_mcl_skins = minetest.get_modpath("mcl_skins") ~= nil local mcl_skins_enabled = minetest.global_exists("mcl_skins")
local def = minetest.registered_items[""]
local list
-- mcl_skins is enabled
if has_mcl_skins == true then
list = mcl_skins.list
else
list = { "hand" }
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 -- This is a fake node that should never be placed in the world
minetest.register_node("mcl_meshhand:"..texture, { local node_def = {
description = "", description = "",
tiles = {texture..".png"},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
visual_scale = 1, visual_scale = 1,
wield_scale = {x=1,y=1,z=1}, wield_scale = {x=1,y=1,z=1},
paramtype = "light", paramtype = "light",
drawtype = "mesh", drawtype = "mesh",
mesh = "mcl_meshhand.b3d",
-- Prevent construction
node_placement_prediction = "", node_placement_prediction = "",
on_construct = function(pos) on_construct = function(pos)
minetest.log("error", "[mcl_meshhand] Trying to construct mcl_meshhand:"..texture.." at "..minetest.pos_to_string(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) minetest.remove_node(pos)
end, end,
drop = "", drop = "",
on_drop = function() on_drop = function() return "" end,
return ""
end,
groups = { dig_immediate = 3, not_in_creative_inventory = 1 }, groups = { dig_immediate = 3, not_in_creative_inventory = 1 },
range = def.range, range = minetest.registered_items[""].range
_mcl_hand_id = texture, }
})
minetest.register_node("mcl_meshhand:"..texture.. "_female", { if mcl_skins_enabled then
description = "", -- Generate a node for every skin
tiles = {texture..".png"}, local list = mcl_skins.get_skin_list()
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, for _, skin in pairs(list) do
visual_scale = 1, if skin.slim_arms then
wield_scale = {x=1,y=1,z=1}, local female = table.copy(node_def)
paramtype = "light", female._mcl_hand_id = skin.id
drawtype = "mesh", female.mesh = "mcl_meshhand_female.b3d"
mesh = "mcl_meshhand_female.b3d", female.tiles = {skin.texture}
-- Prevent construction minetest.register_node("mcl_meshhand:" .. skin.id, female)
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 else
player:get_inventory():set_stack("hand", 1, "mcl_meshhand:"..skin) 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
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 node_id = mcl_skins.get_node_id_by_player(player)
player:get_inventory():set_stack("hand", 1, "mcl_meshhand:" .. node_id)
end) end)
else else
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)

View File

@ -129,7 +129,7 @@ minetest.register_on_joinplayer(function(player)
local name = player:get_player_name() local name = player:get_player_name()
mcl_player.player_attached[name] = false mcl_player.player_attached[name] = false
mcl_player.player_set_model(player, "character.b3d") 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_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, 30)
player:set_fov(86.1) -- see <https://minecraft.gamepedia.com/Options#Video_settings>>>> player:set_fov(86.1) -- see <https://minecraft.gamepedia.com/Options#Video_settings>>>>
end) end)

View File

@ -1,4 +0,0 @@
!textures/mcl_skins_character_1.png
textures/mcl_skins_character_*
!meta/mcl_skins_character_1.txt
meta/mcl_skins_character_*

View File

@ -1,5 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2022 MrRar
Copyright (c) 2016 TenPlus1 Copyright (c) 2016 TenPlus1
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy

View File

@ -1,13 +1,84 @@
= Skins for MineClone 2 = # Mineclone Skins
Simple mod to allow players to select a skin. This mod allows advanced skin customization.
Use the chat command /setskin to change skin. Use the /skin command to open the skin configuration screen.
Forked from Simple Skins by TenPlus1. ## License
https://forum.minetest.net/viewtopic.php?id=9100
== License ==
Code under MIT license Code under MIT license
Origial authors: Author: TenPlus1, Zeg9, MrRar
- TenPlus1
- Zeg9 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.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.
### `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 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)
`skin` is a table with skin item properties.
Returns an image string.

View File

@ -0,0 +1,602 @@
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 = {
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"),
skin = S("Skins"),
},
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 skin = mcl_skins.players[player]
if not skin then return end
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", {
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.compile_skin(skin)
if skin.simple_skins_id then
return mcl_skins.simple_skins[skin.simple_skins_id].texture
end
local output = ""
for i, item in pairs(mcl_skins.item_names) do
local texture = skin[item]
if texture and texture ~= "blank.png" then
if skin[item .. "_color"] and mcl_skins.masks[texture] then
if #output > 0 then output = output .. "^" end
local color = color_to_string(skin[item .. "_color"])
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]
mcl_player.player_set_skin(player, mcl_skins.compile_skin(skin))
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)
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 skin = player:get_meta():get_string("mcl_skins:skin")
if skin then
skin = minetest.deserialize(skin)
end
if skin then
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[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)
mcl_skins.players[player] = nil
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)
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
if page_num < 1 then page_num = 1 end
if mcl_skins[active_tab] then
page_count = math.ceil(#mcl_skins[active_tab] / 16)
if page_num > page_count then
page_num = page_count
end
elseif active_tab == "skin" then
page_count = math.ceil((#mcl_skins.simple_skins + 2) / 8)
if page_num > page_count then
page_num = page_count
end
else
page_num = 1
page_count = 1
end
local formspec = "formspec_version[3]size[13.2,11]"
for i, tab in pairs(mcl_skins.tab_names) do
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] .. "]"
if skin.simple_skins_id then break end
end
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 == "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) ..
",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;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 ..
";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 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_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
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 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;" .. 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
-- 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
local player_name = player:get_player_name()
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)
-- Cancel formspec resend after scrollbar move
if mcl_skins.players[player].form_send_job then
mcl_skins.players[player].form_send_job:cancel()
end
if fields.quit then
mcl_skins.save(player)
return true
end
if fields.alex then
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] = 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]
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].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].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
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
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()

View File

@ -1,280 +1,8 @@
-- Skins for MineClone 2 local mod_path = minetest.get_modpath(minetest.get_current_modname())
local modname = minetest.get_current_modname() local mcl_skins_enabled = minetest.settings:get_bool("mcl_enable_skin_customization", true)
if mcl_skins_enabled then
mcl_skins = { dofile(mod_path .. "/edit_skin.lua")
skins = {}, list = {}, meta = {}, dofile(mod_path .. "/simple_skins.lua")
modpath = minetest.get_modpath(modname), dofile(mod_path .. "/mesh_hand.lua")
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 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("[<player>] [<skin number>]"),
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)")

View File

@ -0,0 +1,260 @@
[
{
"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,
"alex": 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
}
]

View File

@ -1,13 +0,0 @@
# textdomain: mcl_skins
[<player>] [<skin number>]=[<Spieler>] [<Aussehens-Nummer>]
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

View File

@ -1,13 +0,0 @@
# textdomain: mcl_skins
[<player>] [<skin number>]=[<Jugador>] [<Número de skin>]
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

View File

@ -1,14 +1,13 @@
# textdomain: mcl_skins # textdomain: mcl_skins
[<player>] [<skin number>]=[<joueur>] [<numéro d'apparence>] Templates=Modèles
Select player skin of yourself or another player=Sélectionner une apparence pour vous même ou un autre joueur Arm size=Taille des bras
Insufficient or wrong parameters=Paramètres insuffisants ou incorrects Bases=Teint
Player @1 not online!=Le joueur @1 n'est pas en ligne! Footwears=Chaussures
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! Eyes=Yeux
Invalid skin number! Valid numbers: 0 to @1=Numéro d'apparence incorrect! Numéros valides : 0 à @1 Mouths=Bouches
Your skin has been set to: @1=Votre apparence a été définie à: @1 Bottoms=Bas
Your skin has been set to: @1 (@2)=Votre apparence a été définie à: @1 (@2) Tops=Haut
Skin of @1 set to: @2 (@3)=Apparence of @1 set to: @2 (@3)= Hairs=Cheveux
Select player skin:=Sélectionner l'apparence du joueur : Headwears=Coiffe
@1 (@2)=@1 (@2) Open skin configuration screen.=Ouvrir l'écran de configuration du costume.
Name: @1=Nom : @ Select=Sélectionner

View File

@ -1,16 +0,0 @@
# textdomain: mcl_skins
# UNFINISHED translation!
# TODO: Remove the # sign from the translations below and add the missing translations.
[<player>] [<skin number>]=
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

View File

@ -1,13 +0,0 @@
# textdomain: mcl_skins
[<player>] [<skin number>]=[<gracz>] [<numer skina>]
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

View File

@ -1,13 +0,0 @@
# textdomain: mcl_skins
[<player>] [<skin number>]=[<игрок>] [<номер скина>]
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

View File

@ -1,13 +0,0 @@
# textdomain: mcl_skins
[<player>] [<skin number>]=[<玩家名字>] [<皮膚篇號>]
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

View File

@ -1,13 +1,14 @@
# textdomain: mcl_skins # textdomain: mcl_skins
[<player>] [<skin number>]= Skins=
Select player skin of yourself or another player= Templates=
Insufficient or wrong parameters= Arm size=
Player @1 not online!= Bases=
You need the “server” privilege to change the skin of other players!= Footwears=
Invalid skin number! Valid numbers: 0 to @1= Eyes=
Your skin has been set to: @1= Mouths=
Your skin has been set to: @1 (@2)= Bottoms=
Skin of @1 set to: @2 (@3)= Tops=
Select player skin:= Hairs=
@1 (@2)= Headwears=
Name: @1= Open skin configuration screen.=
Select=

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

@ -1,5 +1,4 @@
name = mcl_skins name = mcl_skins
author = TenPlus1 author = MrRar
description = Mod that allows players to set their individual skins. description = Advanced player skin customization.
depends = mcl_player depends = mcl_player,mcl_inventory
optional_depends = mcl_inventory, intllib

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Some files were not shown because too many files have changed in this diff Show More