Merge pull request 'Advanced Skins Mod' (#313) from MrRar/MineClone5:skins into master

Reviewed-on: #313
This commit is contained in:
kay27 2022-07-10 14:27:49 +00:00
commit f2ae6a9d02
104 changed files with 936 additions and 442 deletions

View File

@ -244,17 +244,30 @@ filled_wield_def.on_place = mcl_util.call_on_rightclick
filled_wield_def.groups.no_wieldview = 1
filled_wield_def._wieldview_item = "mcl_maps:empty_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 function player_base_to_node_id(base, colorspec, sex)
return base:gsub("%.", "") .. minetest.colorspec_to_colorstring(colorspec):gsub("#", "") .. sex
end
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)
bases = mcl_skins.base
base_colors = mcl_skins.base_color
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 def = table.copy(filled_wield_def)
def.tiles = {texture}
def.mesh = "mcl_meshhand.b3d"
def._mcl_hand_id = node_id
minetest.register_node("mcl_maps:filled_map_" .. node_id, def)
node_id = player_base_to_node_id(base, base_color, "female")
def = table.copy(filled_wield_def)
def.tiles = {texture}
def.mesh = "mcl_meshhand_female.b3d"
def._mcl_hand_id = node_id
minetest.register_node("mcl_maps:filled_map_" .. node_id, def)
end
end
local old_add_item = minetest.add_item

View File

@ -1,79 +1,56 @@
local has_mcl_skins = minetest.get_modpath("mcl_skins") ~= nil
local def = minetest.registered_items[""]
local list
-- mcl_skins is enabled
if has_mcl_skins == true then
list = mcl_skins.list
else
list = { "hand" }
local bases = mcl_skins.base
local base_colors = mcl_skins.base_color
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,
})
-- 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 = def.range
}
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",
})
-- 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
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)
end
end)
else
minetest.register_on_joinplayer(function(player)
player:get_inventory():set_stack("hand", 1, "mcl_meshhand:hand")
end)
end
-- 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)

View File

@ -1,6 +1,4 @@
name = mcl_meshhand
author = jordan4ibanez
description = Applies the player skin texture to the hand.
depends = mcl_tools
optional_depends = mcl_skins
depends = mcl_tools, mcl_skins

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

View File

@ -1,13 +1,77 @@
= Skins for MineClone 2 =
# Skins for MineClone 5
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.
If texture is not 64x32 then the automatic preview will not display properly.
`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".
If texture is not 64x32 then the automatic preview will not display properly.
`preview`
Set a custom preview texture. You can use texture modifiers. If preview contains the string `{color}` it will be replaced with the item's colorstring.
`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.

View File

@ -0,0 +1,106 @@
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.
Source: https://www.planetminecraft.com/texture-pack/pixel-perfection-chorus-edit/

View File

@ -1,139 +1,165 @@
-- Skins for MineClone 2
-- Skins for MineClone 5
local modname = minetest.get_current_modname()
local S = minetest.get_translator("mcl_skins")
local color_to_string = minetest.colorspec_to_colorstring
mcl_skins = {
skins = {}, list = {}, meta = {},
modpath = minetest.get_modpath(modname),
skin_count = 0, -- counter of _custom_ skins (all skins except character.png)
tab_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"}, -- Rendering order
tab_names_display_order = {"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 = {},
previews = {},
players = {}
}
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()
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
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"
if item.alex then
mcl_skins.alex[item.type] = texture
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
table.insert(mcl_skins[item.type], texture)
mcl_skins.masks[texture] = item.mask
if item.preview then mcl_skins.previews[texture] = item.preview end
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)
function mcl_skins.save(player)
if not player or not player:is_player() then return end
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
function mcl_skins.set_player_skin(player, skin_id)
if not player then
return false
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
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")
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.tab_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
--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
return output
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")
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
-- 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_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
local skin = player:get_meta():get_string("mcl_skins:skin")
if skin then
skin = minetest.deserialize(skin)
end
if not set_skin then
set_skin = math.random(0, mcl_skins.skin_count)
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
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)
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)
@ -143,138 +169,298 @@ 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
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] / 25)
if page_num > page_count then
page_num = page_count
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")
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,10]"
for i, tab in pairs(mcl_skins.tab_names_display_order) 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[9.5,0.3;3,7;player_mesh;" .. mesh .. ";" ..
mcl_skins.compile_skin(skin) ..
",blank.png,blank.png;0,180;false;true;0,0;0]"
if mcl_skins[active_tab] then
local textures = mcl_skins[active_tab]
local page_start = (page_num - 1) * 25 + 1
local page_end = math.min(page_start + 25 - 1, #textures)
for j = page_start, page_end do
local i = j - page_start + 1
local texture = textures[j]
local preview = ""
if mcl_skins.previews[texture] then
preview = mcl_skins.previews[texture]
if skin[active_tab .. "_color"] then
local color = minetest.colorspec_to_colorstring(skin[active_tab .. "_color"])
preview = preview:gsub("{color}", color)
end
elseif active_tab == "base" then
if mcl_skins.masks[texture] then
preview = mcl_skins.masks[texture] .. "^[sheet:8x4:1,1" ..
"^[colorize:" .. color_to_string(skin.base_color) .. ":alpha"
end
if #preview > 0 then preview = preview .. "^" end
preview = preview .. "(" .. texture .. "^[sheet:8x4:1,1)"
elseif active_tab == "mouth" or active_tab == "eye" then
preview = texture .. "^[sheet:8x4:1,1"
elseif active_tab == "headwear" then
preview = texture .. "^[sheet:8x4:5,1^(" .. texture .. "^[sheet:8x4:1,1)"
elseif active_tab == "hair" then
if mcl_skins.masks[texture] then
preview = mcl_skins.masks[texture] .. "^[sheet:8x4:1,1" ..
"^[colorize:" .. color_to_string(skin.hair_color) .. ":alpha^(" ..
texture .. "^[sheet:8x4:1,1)^(" ..
mcl_skins.masks[texture] .. "^[sheet:8x4:5,1" ..
"^[colorize:" .. color_to_string(skin.hair_color) .. ":alpha)" ..
"^(" .. texture .. "^[sheet:8x4:5,1)"
else
preview = texture .. "^[sheet:8x4:5,1"
end
elseif active_tab == "top" then
if mcl_skins.masks[texture] then
preview = "[combine:12x12:-18,-20=" .. mcl_skins.masks[texture] ..
"^[colorize:" .. color_to_string(skin.top_color) .. ":alpha"
end
if #preview > 0 then preview = preview .. "^" end
preview = preview .. "[combine:12x12:-18,-20=" .. texture .. "^[mask:mcl_skins_top_preview_mask.png"
elseif active_tab == "bottom" then
if mcl_skins.masks[texture] then
preview = "[combine:12x12:0,-20=" .. mcl_skins.masks[texture] ..
"^[colorize:" .. color_to_string(skin.bottom_color) .. ":alpha"
end
if #preview > 0 then preview = preview .. "^" end
preview = preview .. "[combine:12x12:0,-20=" .. texture .. "^[mask:mcl_skins_bottom_preview_mask.png"
elseif active_tab == "footwear" then
preview = "[combine:12x12:0,-20=" .. texture .. "^[mask:mcl_skins_bottom_preview_mask.png"
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!")
if skin[active_tab] == texture then
preview = preview .. "^mcl_skins_select_overlay.png"
end
i = i - 1
local x = 3.6 + i % 5 * 1.1
local y = 0.3 + math.floor(i / 5) * 1.1
formspec = formspec ..
"image_button[" .. x .. "," .. y ..
";1,1;" .. preview .. ";" .. 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 ""
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;]"
elseif active_tab == "template" then
formspec = formspec ..
"model[4,2;2,3;player_mesh;" .. mesh .. ";" ..
mcl_skins.compile_skin(mcl_skins.steve) ..
",blank.png,blank.png;0,180;false;true;0,0;0]" ..
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
"button[4,5.2;2,0.8;steve;" .. S("Select") .. "]" ..
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")
"model[6.5,2;2,3;player_mesh;" .. mesh .. ";" ..
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") .. "]"
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"
for i, colorspec in pairs(colors) do
local overlay = ""
if skin[tab_color] == colorspec then
overlay = "^mcl_skins_select_overlay.png"
end
else
-- Show skin selection formspec otherwise
mcl_skins.show_formspec(player:get_player_name())
local color = minetest.colorspec_to_colorstring(colorspec)
i = i - 1
local x = 3.6 + i % 8 * 1.1
local y = 7 + math.floor(i / 8) * 1.1
formspec = formspec ..
"image_button[" .. x .. "," .. y ..
";1,1;blank.png^[noalpha^[colorize:" ..
color .. ":alpha" .. overlay .. ";" .. colorspec .. ";]"
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
if page_num > 1 then
formspec = formspec ..
"image_button[3.6,5.8;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]"
end
if page_num < page_count then
formspec = formspec ..
"image_button[8,5.8;1,1;mcl_skins_arrow.png;next_page;]"
end
if page_count > 1 then
formspec = formspec ..
"label[5.9,6.3;" .. page_num .. " / " .. page_count .. "]"
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)
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 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
if not formname:find("^mcl_skins:") then return false end
local _, _, active_tab, page_num = formname:find("^mcl_skins:(%a+)_(%d+)")
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()
for field, value in pairs(fields) do
if field == "quit" then
mcl_skins.save(player)
return true
end
if field == "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 field == "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_display_order) do
if field == 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 field == "next_page" then
page_num = page_num + 1
mcl_skins.show_formspec(player, active_tab, page_num)
return true
elseif field == "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 field == "thick_arms" then
skin.slim_arms = false
elseif field == "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
-- See if field is a texture
if 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
if skin[active_tab .. "_color"] then
local color = math.floor(tonumber(field) or 0)
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
mcl_skins.set_player_skin(player, skin_id)
mcl_skins.show_formspec(name)
end
end
return true
end)
minetest.log("action", "[mcl_skins] Mod initialized with "..mcl_skins.skin_count.." custom skin(s)")
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
mcl_skins.modpath = minetest.get_modpath("mcl_skins")
local f = io.open(mcl_skins.modpath .. "/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
mcl_skins.previews["blank.png"] = "blank.png"
end
init()

View File

@ -0,0 +1,256 @@
[
{
"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": "mcl_skins_headwear_6.png^[sheet:8x4:7,1"
},
{
"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
}
]

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 +0,0 @@
# textdomain: mcl_skins
[<player>] [<skin number>]=[<joueur>] [<numéro d'apparence>]
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 en : @1
Your skin has been set to: @1 (@2)=Votre apparence a été définie en : @1 (@2)
Skin of @1 set to: @2 (@3)=Apparence de @1 definie en : @2 (@3)
Select player skin:=Sélectionner l'apparence du joueur :
@1 (@2)=@1 (@2)
Name: @1=Nom : @1

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!=你需要“服务器”特权来改变其他玩家的皮肤!
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 +1,13 @@
# textdomain: mcl_skins
[<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:=
@1 (@2)=
Name: @1=
Templates=
Arm size=
Bases=
Footwears=
Eyes=
Mouths=
Bottoms=
Tops=
Hairs=
Headwears=
Open skin configuration screen.=
Select=

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

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.

After

Width:  |  Height:  |  Size: 89 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: 167 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 960 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

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