Add advanced skins mod

This commit is contained in:
parent 0ad52fd949
commit 4ca2fb25a7
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.groups.no_wieldview = 1
filled_wield_def._wieldview_item = "mcl_maps:empty_map" filled_wield_def._wieldview_item = "mcl_maps:empty_map"
for _, texture in pairs(mcl_skins.list) do local function player_base_to_node_id(base, colorspec, sex)
local def = table.copy(filled_wield_def) return base:gsub("%.", "") .. minetest.colorspec_to_colorstring(colorspec):gsub("#", "") .. sex
def.tiles = {texture .. ".png"} end
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) bases = mcl_skins.base
female_def.mesh = "mcl_meshhand_female.b3d" base_colors = mcl_skins.base_color
female_def._mcl_hand_id = texture .. "_female"
minetest.register_node("mcl_maps:filled_map_" .. texture .. "_female", female_def) 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 end
local old_add_item = minetest.add_item 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 def = minetest.registered_items[""]
local list local bases = mcl_skins.base
-- mcl_skins is enabled local base_colors = mcl_skins.base_color
if has_mcl_skins == true then
list = mcl_skins.list local function player_base_to_node_id(base, colorspec, sex)
else return base:gsub("%.", "") .. minetest.colorspec_to_colorstring(colorspec):gsub("#", "") .. sex
list = { "hand" }
end end
--generate a node for every skin -- This is a fake node that should never be placed in the world
for _,texture in pairs(list) do local node_def = {
-- This is a fake node that should never be placed in the world description = "",
minetest.register_node("mcl_meshhand:"..texture, { use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
description = "", visual_scale = 1,
tiles = {texture..".png"}, wield_scale = {x=1,y=1,z=1},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, paramtype = "light",
visual_scale = 1, drawtype = "mesh",
wield_scale = {x=1,y=1,z=1}, node_placement_prediction = "",
paramtype = "light", on_construct = function(pos)
drawtype = "mesh", local name = get_node(pos).name
mesh = "mcl_meshhand.b3d", local message = "[mcl_meshhand] Trying to construct " .. name .. " at " .. minetest.pos_to_string(pos)
-- Prevent construction minetest.log("error", message)
node_placement_prediction = "", minetest.remove_node(pos)
on_construct = function(pos) end,
minetest.log("error", "[mcl_meshhand] Trying to construct mcl_meshhand:"..texture.." at "..minetest.pos_to_string(pos)) drop = "",
minetest.remove_node(pos) on_drop = function() return "" end,
end, groups = { dig_immediate = 3, not_in_creative_inventory = 1 },
drop = "", range = def.range
on_drop = function() }
return ""
end,
groups = { dig_immediate = 3, not_in_creative_inventory = 1 },
range = def.range,
_mcl_hand_id = texture,
})
minetest.register_node("mcl_meshhand:"..texture.. "_female", { -- Generate a node for every skin
description = "", for _, base in pairs(bases) do
tiles = {texture..".png"}, for _, base_color in pairs(base_colors) do
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, local node_id = player_base_to_node_id(base, base_color, "male")
visual_scale = 1, local texture = mcl_skins.make_hand_texture(base, base_color)
wield_scale = {x=1,y=1,z=1}, local male = table.copy(node_def)
paramtype = "light", male._mcl_hand_id = node_id
drawtype = "mesh", male.mesh = "mcl_meshhand.b3d"
mesh = "mcl_meshhand_female.b3d", male.tiles = {texture}
-- Prevent construction minetest.register_node("mcl_meshhand:" .. node_id, male)
node_placement_prediction = "",
on_construct = function(pos) node_id = player_base_to_node_id(base, base_color, "female")
minetest.log("error", "[mcl_meshhand] Trying to construct mcl_meshhand:"..texture.." at "..minetest.pos_to_string(pos)) local female = table.copy(node_def)
minetest.remove_node(pos) female._mcl_hand_id = node_id
end, female.mesh = "mcl_meshhand_female.b3d"
drop = "", female.tiles = {texture}
on_drop = function() minetest.register_node("mcl_meshhand:" .. node_id, female)
return "" end
end,
groups = { dig_immediate = 3, not_in_creative_inventory = 1 },
range = def.range,
_mcl_hand_id = texture .. "_female",
})
end end
if has_mcl_skins == true then -- Change the player's hand to their skin
--change the player's hand to their skin mcl_skins.register_on_set_skin(function(player)
mcl_skins.register_on_set_skin(function(player, skin) local data = mcl_skins.players[player:get_player_name()]
local meta = mcl_skins.meta[skin] local node_id = player_base_to_node_id(data.base, data.base_color, data.slim_arms and "female" or "male")
if meta.gender == "female" then player:get_inventory():set_stack("hand", 1, "mcl_meshhand:" .. node_id)
player:get_inventory():set_stack("hand", 1, "mcl_meshhand:"..skin.."_female") end)
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

View File

@ -1,6 +1,4 @@
name = mcl_meshhand name = mcl_meshhand
author = jordan4ibanez author = jordan4ibanez
description = Applies the player skin texture to the hand. description = Applies the player skin texture to the hand.
depends = mcl_tools depends = mcl_tools, mcl_skins
optional_depends = 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) 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal 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. 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: 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.
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 = { mcl_skins = {
skins = {}, list = {}, meta = {}, tab_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"}, -- Rendering order
modpath = minetest.get_modpath(modname), tab_names_display_order = {"template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"},
skin_count = 0, -- counter of _custom_ skins (all skins except character.png) 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) function mcl_skins.register_item(item)
local has_mcl_inventory = minetest.get_modpath("mcl_inventory") assert(mcl_skins[item.type], "Skin item type " .. item.type .. " does not exist.")
local texture = item.texture or "blank.png"
-- load skin list and metadata if item.steve then
local id, f, data, skin = 0 mcl_skins.steve[item.type] = texture
while true do
if id == 0 then
skin = "character"
else
skin = "mcl_skins_character_" .. id
-- Does skin file exist?
f = io.open(mcl_skins.modpath .. "/textures/" .. skin .. ".png")
-- escape loop if not found
if not f then
break
end
f:close()
end end
mcl_skins.list[id] = skin if item.alex then
mcl_skins.alex[item.type] = texture
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 end
f = io.open(mcl_skins.modpath .. "/meta/" .. metafile)
table.insert(mcl_skins[item.type], texture)
data = nil mcl_skins.masks[texture] = item.mask
if f then if item.preview then mcl_skins.previews[texture] = item.preview end
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 end
function mcl_skins.cycle_skin(player) function mcl_skins.save(player)
local skin_id = tonumber(player:get_meta():get_string("mcl_skins:skin_id")) if not player or not player:is_player() then return end
if not skin_id then local name = player:get_player_name()
skin_id = 0 local skin = mcl_skins.players[name]
end if not skin then return end
skin_id = skin_id + 1 player:get_meta():set_string("mcl_skins:skin", minetest.serialize(skin))
if skin_id > mcl_skins.skin_count then
skin_id = 0
end
mcl_skins.set_player_skin(player, skin_id)
end end
function mcl_skins.set_player_skin(player, skin_id) minetest.register_chatcommand("skin", {
if not player then description = S("Open skin configuration screen."),
return false 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 end
local playername = player:get_player_name() if #output > 0 then output = output .. "^" end
local skin output = output .. base
if skin_id == nil or type(skin_id) ~= "number" or skin_id < 0 or skin_id > mcl_skins.skin_count then return output
return false end
elseif skin_id == 0 then
skin = "character" function mcl_skins.compile_skin(skin)
mcl_player.player_set_model(player, "mcl_armor_character.b3d") local output = ""
else for i, tab in pairs(mcl_skins.tab_names) do
skin = "mcl_skins_character_" .. tostring(skin_id) local texture = skin[tab]
local meta = mcl_skins.meta[skin] if texture and texture ~= "blank.png" then
if meta.gender == "female" then
mcl_player.player_set_model(player, "mcl_armor_character_female.b3d") if skin[tab .. "_color"] and mcl_skins.masks[texture] then
else if #output > 0 then output = output .. "^" end
mcl_player.player_set_model(player, "mcl_armor_character.b3d") 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
end end
--local skin_file = skin .. ".png" return output
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 end
function mcl_skins.update_player_skin(player) function mcl_skins.update_player_skin(player)
if not player then if not player then
return return
end 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 end
-- load player skin on join -- Load player skin on join
minetest.register_on_joinplayer(function(player) 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 name = player:get_player_name()
local skin_id = player:get_meta():get_string("mcl_skins:skin_id") local skin = player:get_meta():get_string("mcl_skins:skin")
local set_skin if skin then
-- do we already have a skin in player attributes? skin = minetest.deserialize(skin)
if skin_id and skin_id ~= "" then
set_skin = tonumber(skin_id)
-- otherwise use random skin if not set
end end
if not set_skin then if skin then
set_skin = math.random(0, mcl_skins.skin_count) 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 end
local ok = mcl_skins.set_player_skin(player, set_skin) mcl_skins.save(player)
if not ok then mcl_skins.update_player_skin(player)
set_skin = math.random(0, mcl_skins.skin_count) end)
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) minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
if name then
mcl_skins.players[name] = nil
end end
end) end)
@ -143,138 +169,298 @@ function mcl_skins.register_on_set_skin(func)
table.insert(mcl_skins.registered_on_set_skins, func) table.insert(mcl_skins.registered_on_set_skins, func)
end end
-- command to set player skin (usually for custom skins) function mcl_skins.show_formspec(player, active_tab, page_num)
minetest.register_chatcommand("setskin", { active_tab = active_tab or "template"
params = S("[<player>] [<skin number>]"), page_num = page_num or 1
description = S("Select player skin of yourself or another player"),
privs = {}, local page_count
func = function(name, param) if page_num < 1 then page_num = 1 end
if mcl_skins[active_tab] then
if param == "" and name ~= "" then page_count = math.ceil(#mcl_skins[active_tab] / 25)
mcl_skins.show_formspec(name) if page_num > page_count then
return true page_num = page_count
end end
local playername, skin_id = string.match(param, "([^ ]+) (%d+)") else
if not playername or not skin_id then page_num = 1
skin_id = string.match(param, "(%d+)") page_count = 1
if not skin_id then end
return false, S("Insufficient or wrong parameters")
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 end
playername = name
end if skin[active_tab] == texture then
skin_id = tonumber(skin_id) preview = preview .. "^mcl_skins_select_overlay.png"
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
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 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) "button[4,5.2;2,0.8;steve;" .. S("Select") .. "]" ..
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]] "model[6.5,2;2,3;player_mesh;" .. mesh .. ";" ..
local your_msg mcl_skins.compile_skin(mcl_skins.alex) ..
if not meta.name or meta.name == "" then ",blank.png,blank.png;0,180;false;true;0,0;0]" ..
your_msg = S("Your skin has been set to: @1", skinfile)
else "button[6.5,5.2;2,0.8;alex;" .. S("Select") .. "]"
your_msg = S("Your skin has been set to: @1 (@2)", meta.name, skinfile)
end end
if name == playername then
return true, your_msg if skin[active_tab .. "_color"] then
else local colors = mcl_skins.color
minetest.chat_send_player(playername, your_msg) if active_tab == "base" then colors = mcl_skins.base_color end
return true, S("Skin of @1 set to: @2 (@3)", playername, meta.name, skinfile)
end local tab_color = active_tab .. "_color"
end, for i, colorspec in pairs(colors) do
}) local overlay = ""
if skin[tab_color] == colorspec then
minetest.register_on_player_receive_fields(function(player, formname, fields) overlay = "^mcl_skins_select_overlay.png"
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 end
else
-- Show skin selection formspec otherwise local color = minetest.colorspec_to_colorstring(colorspec)
mcl_skins.show_formspec(player:get_player_name()) 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 end
end)
if page_num > 1 then
function mcl_skins.show_formspec(playername) formspec = formspec ..
local formspec = "size[7,8.5]" "image_button[3.6,5.8;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]"
end
formspec = formspec .. "label[2,2;" .. minetest.formspec_escape(minetest.colorize("#383838", S("Select player skin:"))) .. "]"
.. "textlist[0,2.5;6.8,6;skins_set;" if page_num < page_count then
formspec = formspec ..
local meta "image_button[8,5.8;1,1;mcl_skins_arrow.png;next_page;]"
local selected = 1 end
for i = 0, mcl_skins.skin_count do if page_count > 1 then
formspec = formspec ..
local label = S("@1 (@2)", mcl_skins.meta[mcl_skins.list[i]].name, "#"..i) "label[5.9,6.3;" .. page_num .. " / " .. page_count .. "]"
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 end
formspec = formspec .. ";" .. selected .. ";false]" minetest.show_formspec(player_name, "mcl_skins:" .. active_tab .. "_" .. page_num, formspec)
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 end
minetest.register_on_player_receive_fields(function(player, formname, fields) 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 if not formname:find("^mcl_skins:") then return false end
local _, _, active_tab, page_num = formname:find("^mcl_skins:(%a+)_(%d+)")
local name = player:get_player_name() if not page_num or not active_tab then return true end
page_num = math.floor(tonumber(page_num) or 1)
local event = minetest.explode_textlist_event(fields["skins_set"]) local player_name = player:get_player_name()
if event.type == "CHG" or event.type == "DCL" then for field, value in pairs(fields) do
if field == "quit" then
local skin_id = math.min(event.index - 1, mcl_skins.skin_count) mcl_skins.save(player)
if not mcl_skins.list[skin_id] then return true
return -- Do not update wrong skin number 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 end
mcl_skins.set_player_skin(player, skin_id)
mcl_skins.show_formspec(name)
end end
end end
return true
end) 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 # textdomain: mcl_skins
[<player>] [<skin number>]= Templates=
Select player skin of yourself or another player= Arm size=
Insufficient or wrong parameters= Bases=
Player @1 not online!= Footwears=
You need the “server” privilege to change the skin of other players!= Eyes=
Invalid skin number! Valid numbers: 0 to @1= Mouths=
Your skin has been set to: @1= Bottoms=
Your skin has been set to: @1 (@2)= Tops=
Skin of @1 set to: @2 (@3)= Hairs=
Select player skin:= Headwears=
@1 (@2)= Open skin configuration screen.=
Name: @1= 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 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

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