Compare commits

..

2 Commits

47 changed files with 279 additions and 339 deletions

View File

@ -308,7 +308,7 @@ local function dir_to_pitch(dir)
return -math.atan2(-dir.y, xz)
end
local function who_are_you_looking_at (self, dtime)
local function who_are_you_looking_at (self)
local pos = self.object:get_pos()
local stop_look_at_player_chance = math.random(833/self.curiosity)
@ -361,7 +361,7 @@ function mob_class:check_head_swivel(dtime)
if not self.head_swivel or type(self.head_swivel) ~= "string" then return end
who_are_you_looking_at (self, dtime)
who_are_you_looking_at (self)
local final_rotation = vector.zero()
local oldp,oldr = self.object:get_bone_position(self.head_swivel)

View File

@ -823,7 +823,7 @@ end
function mob_class:step_damage (dtime, pos)
if not self.fire_resistant then
mcl_burning.tick(self.object, dtime, self)
if not self.object:get_pos() then return true end -- mcl_burning.tick may remove object immediately
if not self.object:get_pos() then return end -- mcl_burning.tick may remove object immediately
if self:check_for_death("fire", {type = "fire"}) then
return true

View File

@ -82,7 +82,7 @@ mcl_mobs.register_mob("mobs_mc:pig", {
end
-- if driver present allow control of horse
if self.driver and self.driver:get_wielded_item():get_name() == "mcl_mobitems:carrot_on_a_stick" then
if self.driver then
mcl_mobs.drive(self, "walk", "stand", false, dtime)
@ -149,14 +149,18 @@ mcl_mobs.register_mob("mobs_mc:pig", {
return
end
-- Should make pig go faster when right clicked with carrot on a stick.
-- FIXME: needs work on the going faster part.
--[[if self.driver and clicker == self.driver and self.driver:get_wielded_item():get_name() == "mcl_mobitems:carrot_on_a_stick" then
if not self.v3 then
self.v3 = 0
self.max_speed_forward = 100
self.accel = 10
end
-- Mount or detach player
local name = clicker:get_player_name()
if self.driver and clicker == self.driver then
-- Detach if already attached
mcl_mobs.detach(clicker, {x=1, y=0, z=0})
return
elseif not self.driver and self.saddle == "yes" and wielditem:get_name() == "mcl_mobitems:carrot_on_a_stick" then
-- Ride pig if it has a saddle and player uses a carrot on a stick
mcl_mobs.attach(self, clicker)
if not minetest.is_creative_enabled(clicker:get_player_name()) then
local inv = self.driver:get_inventory()
@ -173,19 +177,6 @@ mcl_mobs.register_mob("mobs_mc:pig", {
end
inv:set_stack("main",self.driver:get_wield_index(), wielditem)
end
end]]
-- Mount or detach player
local name = clicker:get_player_name()
if self.driver and clicker == self.driver then -- and self.driver:get_wielded_item():get_name() ~= "mcl_mobitems:carrot_on_a_stick" then -- Note: This is for when the ability to make the pig go faster is implemented
-- Detach if already attached
mcl_mobs.detach(clicker, {x=1, y=0, z=0})
return
elseif not self.driver and self.saddle == "yes" then
-- Ride pig if it has a saddle
mcl_mobs.attach(self, clicker)
return
-- Capture pig
@ -204,18 +195,6 @@ mcl_mobs.register_mob("mobs_mc:pig", {
return false
end
end,
after_activate = function(self, staticdata, def, dtime)
if self.saddle == "yes" then -- Make saddle load upon rejoin
self.base_texture = {
"mobs_mc_pig.png", -- base
"mobs_mc_pig_saddle.png", -- saddle
}
self.object:set_properties({
textures = self.base_texture
})
end
end,
})
mcl_mobs:spawn_specific(

View File

@ -84,7 +84,9 @@ minetest.register_entity(":mcl_raids:ominous_banner",oban_def)
function mcl_raids.drop_obanner(pos)
local it = ItemStack("mcl_banners:banner_item_white")
it:get_meta():set_string("layers",minetest.serialize(oban_layers))
it:get_meta():set_string("name",S("Ominous Banner"))
local banner_description = string.gsub(it:get_definition().description, "White Banner", "Ominous Banner")
local description = mcl_banners.make_advanced_banner_description(banner_description, oban_layers)
it:get_meta():set_string("description", description)
minetest.add_item(pos,it)
end
@ -94,7 +96,7 @@ function mcl_raids.promote_to_raidcaptain(c) -- object
local l = c:get_luaentity()
l._banner = minetest.add_entity(pos,"mcl_raids:ominous_banner")
l._banner:set_properties({textures = {mcl_banners.make_banner_texture("unicolor_white", oban_layers)}})
l._banner:set_attach(c,"",vector.new(-1,5.5,0),vector.new(0,0,0),true)
l._banner:set_attach(c,"",vector.new(0,5.5,0),vector.new(0,0,0),true)
l._raidcaptain = true
local old_ondie = l.on_die
l.on_die = function(self, pos, cmi_cause)
@ -129,7 +131,7 @@ function mcl_raids.register_possible_raidcaptain(mob)
table.insert(minetest.registered_entities[mob].pick_up,"mcl_banners:banner_item_white")
minetest.registered_entities[mob].on_pick_up = function(self,e)
local stack = ItemStack(e.itemstring)
if not self._raidcaptain and stack:get_meta():get_string("name"):find("Ominous Banner") then
if not self._raidcaptain and stack:get_meta():get_string("description"):find("Ominous Banner") then
stack:take_item(1)
mcl_raids.promote_to_raidcaptain(self.object)
return stack

View File

@ -1,3 +1,3 @@
name = mcl_raids
author = PrairieWind
depends = mcl_events, mobs_mc, mcl_potions, mcl_bells, mcl_achievements
depends = mcl_events, mobs_mc, mcl_potions, mcl_bells, mcl_achievements, mcl_banners

View File

@ -198,7 +198,7 @@ awards.register_achievement("mcl:skysTheLimit", {
-- Smelting achivements: These are awarded when picking up an item from a furnace
-- output. They are given in mcl_furnaces.
awards.register_achievement("mcl:acquireIron", {
title = S("Acquire Hardware"),
title = S("Aquire Hardware"),
description = S("Take an iron ingot from a furnace's output slot.\nHint: To smelt an iron ingot, put a fuel (like coal) and iron ore into a furnace."),
icon = "default_steel_ingot.png",
type = "Advancement",

View File

@ -1,5 +1,5 @@
# textdomain:mcl_achievements
Acquire Hardware=Schmied
Aquire Hardware=Schmied
Bake Bread=Brot backen
Benchmarking=Tischler
Cow Tipper=Kuhschubser

View File

@ -1,5 +1,5 @@
# textdomain:mcl_achievements
Acquire Hardware=Obteniendo un lingote
Aquire Hardware=Obteniendo un lingote
Bake Bread=Horneando pan
Benchmarking=Crea tu mesa de trabajo
Cow Tipper=Consiguiendo cuero

View File

@ -1,5 +1,5 @@
# textdomain:mcl_achievements
Acquire Hardware=Acquérir du matériel
Aquire Hardware=Acquérir du matériel
Bake Bread=Faire du pain
Benchmarking=Fabriquer
Cow Tipper=Chevaucher une vache

View File

@ -1,5 +1,5 @@
# textdomain:mcl_achievements
Acquire Hardware=金属を入手
Aquire Hardware=金属を入手
Bake Bread=パンを焼く
Benchmarking=土台作り
Cow Tipper=牛転がし

View File

@ -1,5 +1,5 @@
# textdomain:mcl_achievements
Acquire Hardware=Zdobądź narzędzie
Aquire Hardware=Zdobądź narzędzie
Bake Bread=Upiecz chleb
Benchmarking=Rzemieślnictwo
Cow Tipper=Raz krowie śmierć

View File

@ -1,5 +1,5 @@
# textdomain:mcl_achievements
Acquire Hardware=Куй Железо
Aquire Hardware=Куй Железо
Bake Bread=Хлеб всему голова
Benchmarking=Верстак
Cow Tipper=Кожа да кости

View File

@ -1,5 +1,5 @@
# textdomain:mcl_achievements
Acquire Hardware=
Aquire Hardware=
Bake Bread=
Benchmarking=
Cow Tipper=

View File

@ -158,10 +158,8 @@ minetest.register_on_player_inventory_action(function(player, action, inventory,
end)
minetest.register_on_joinplayer(function(player)
mcl_player.player_set_model(player, "mcl_armor_character.b3d")
player:get_inventory():set_size("armor", 5)
if not minetest.global_exists("mcl_skins") then
mcl_player.player_set_model(player, "mcl_armor_character.b3d")
end
minetest.after(1, function()
if player:is_player() then

View File

@ -493,6 +493,16 @@ for colorid, colortab in pairs(mcl_banners.colors) do
end
end
-- Update old pre 0.84.0 Ominous Banners with correct description.
local stackmeta = itemstack:get_meta()
if stackmeta:get_string("name"):find("Ominous Banner") then
local oban_layers = minetest.deserialize(stackmeta:get_string("layers"))
local banner_description = string.gsub(itemstack:get_definition().description, "White Banner", "Ominous Banner")
local description = mcl_banners.make_advanced_banner_description(banner_description, oban_layers)
stackmeta:set_string("description", description)
stackmeta:set_string("name", nil)
end
-- Place the node!
local hanging = false

View File

@ -76,3 +76,4 @@ You can copy the pattern of a banner by placing two banners of the same color in
And one additional layer=
And @1 additional layers=
Paintable decoration=
Ominous Banner=

View File

@ -63,7 +63,7 @@ local function barrel_open(pos, node, clicker)
minetest.swap_node(pos, { name = "mcl_barrels:barrel_open", param2 = node.param2 })
open_barrels[playername] = pos
minetest.sound_play({name="mcl_barrels_default_barrel_open", pos=pos, gain=0.5, max_hear_distance=16}, true)
minetest.sound_play({name="mcl_barrels_default_barrel_open", pos=node_pos, gain=0.5, max_hear_distance=16}, true)
end
local function close_forms(pos)
@ -81,7 +81,7 @@ local function update_after_close(pos)
if not node then return end
if node.name == "mcl_barrels:barrel_open" then
minetest.swap_node(pos, {name = "mcl_barrels:barrel_closed", param2 = node.param2})
minetest.sound_play({name="mcl_barrels_default_barrel_close", pos=pos, gain=0.5, max_hear_distance=16}, true)
minetest.sound_play({name="mcl_barrels_default_barrel_close", pos=node_pos, gain=0.5, max_hear_distance=16}, true)
end
end

View File

@ -1,4 +1,4 @@
name = mcl_signs
description = New and Improved signs - can be colored and made to glow.
depends = mcl_core, mcl_sounds, mcl_dye, mcl_colors, mcl_util
depends = mcl_core, mcl_sounds, mcl_dye, mcl_colors
optional_depends = doc

View File

@ -307,9 +307,7 @@ mcl_signs.wall_standard = {
local item = clicker:get_wielded_item()
local iname = item:get_name()
local protected = mcl_util.check_position_protection(pos, clicker)
if node and not protected then
if node then
if DEBUG then
minetest.log("verbose", "[mcl_signs] Wall_Sign Right Click event on valid node.")
end
@ -416,9 +414,7 @@ mcl_signs.standing_standard = {
local item = clicker:get_wielded_item()
local iname = item:get_name()
local protected = mcl_util.check_position_protection(pos, clicker)
if node and not protected then
if node then
-- handle glow from glow_ink_sac *first*
if DEBUG then
minetest.log("verbose", "[mcl_signs] Standing_Sign Right Click event on valid node.")

View File

@ -335,7 +335,7 @@ local function set_water_palette(minp,maxp,data2,area,biomemap,nodes)
return lvm_used
end
local function set_seagrass_param2(minp,maxp,data2,area,nodes)
local function set_seagrass_param2(minp,maxp,data2,area,biomemap,nodes)
local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}})
local nodes = minetest.find_nodes_in_area(minp, maxp, nodes)
for n=1, #nodes do
@ -440,7 +440,7 @@ local function block_fixes_seagrass(vm, data, data2, emin, emax, area, minp, max
local pr = PseudoRandom(blockseed)
if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then
-- Set param2 of seagrass to 3.
lvm_used = set_seagrass_param2(minp, maxp, data2, area, {"group:seagrass"})
lvm_used = set_seagrass_param2(minp,maxp,data2,area,biomemap,{"group:seagrass"})
end
return lvm_used
end

View File

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

View File

@ -28,6 +28,28 @@ function mcl_player.player_register_model(name, def)
models[name] = def
end
-- Default player appearance
mcl_player.player_register_model("character.b3d", {
animation_speed = 30,
textures = {"character.png", },
animations = {
-- Standard animations.
stand = {x= 0, y= 79},
lay = {x=162, y=166},
walk = {x=168, y=187},
mine = {x=189, y=198},
walk_mine = {x=200, y=219},
sit = {x= 81, y=160},
sneak_stand = {x=222, y=302},
sneak_mine = {x=346, y=366},
sneak_walk = {x=304, y=323},
sneak_walk_mine = {x=325, y=344},
run_walk = {x=440, y=460},
run_walk_mine = {x=461, y=481},
sit_mount = {x=484, y=484},
},
})
-- Player stats and animations
local player_model = {}
local player_textures = {}
@ -90,7 +112,6 @@ function mcl_player.player_set_model(player, model_name)
if player_model[name] == model_name then
return
end
player_model[name] = model_name
player:set_properties({
mesh = model_name,
visual = "mesh",
@ -98,20 +119,14 @@ function mcl_player.player_set_model(player, model_name)
damage_texture_modifier = "^[colorize:red:130",
})
update_player_textures(player)
local new_anim = "stand"
local model_animations = models[model_name].animations
local old_anim = player_anim[name]
if model_animations and old_anim and model_animations[old_anim] then
new_anim = old_anim
end
mcl_player.player_set_animation(player, new_anim)
mcl_player.player_set_animation(player, "stand")
else
player:set_properties({
textures = { "player.png", "player_back.png", },
visual = "upright_sprite",
})
end
player_model[name] = model_name
end
function mcl_player.player_set_visibility(player, visible)
@ -165,6 +180,7 @@ minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
mcl_player.player_attached[name] = false
player_visible[name] = true
mcl_player.player_set_model(player, "character.b3d")
player_textures[name] = {"character.png", "blank.png", "blank.png"}
--player:set_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, 30)
player:set_fov(86.1) -- see <https://minecraft.gamepedia.com/Options#Video_settings>>>>

Binary file not shown.

Binary file not shown.

View File

@ -3,11 +3,9 @@
This mod allows advanced skin customization.
Use the /skin command to open the skin configuration screen.
To include custom skins in MineClone2, please download [mcl_custom_skins](https://git.minetest.land/mineclone2/mcl_custom_skins)
## License
Code under MIT license
Author: MrRar
Author: TenPlus1, Zeg9, MrRar
See image_credits.txt for image licensing.
@ -17,7 +15,6 @@ See image_credits.txt for image licensing.
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"
@ -31,40 +28,16 @@ Coloring only works for "base", "bottom, "top", and "hair".
`preview_rotation`
A table containing properties x and y. x and y represent the x and y rotation of the item preview.
`template2`
If set to true the item will be default for female template.
`alex`
If set to true the item will be default for female character.
`template1`
If set to true the item will be default for male template.
`rank`
This property is used to change the application order of the skin item when applied to a player.
The default ranks for each item type are:
base: 10
footwear: 20
eye: 30
mouth: 40
bottom: 50
top: 60
hair: 70
headwear: 80
Lower ranks are applied to the player first and can thus be covered by higher rank items.
`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"
@ -77,9 +50,7 @@ Returns an array of tables containing information about each skin.
Each table contains the following properties:
`id`: A string representing the node ID. A node can be registered using this node ID.
`texture`: A texture string that can be used in the node defintion.
`slim_arms`: A boolean value. If true, this texture is used with the "female" player mesh. Otherwise the regular mesh is to be used.
### `mcl_skins.get_node_id_by_player(player)`
@ -100,19 +71,10 @@ These colors are separate from `mcl_skins.color` because some mods register two
### `mcl_skins.color`
A table of ColorSpec integers that the player can select to color colorable skin items.
### `mcl_skins.player_skins`
### `mcl_skins.players`
A table mapped by player ObjectRef containing tables holding the player's selected skin items and colors.
Only stores skin information for logged in users.
### `mcl_skins.compile_skin(skin)`
### mcl_skins.compile_skin(skin)
`skin` is a table with skin item properties.
Returns an image string.
### `mcl_skins.register_simple_skin(skin)`
`skin` is a table with the following properties:
`texture`
The texture of the skin.
`slim_arms`
A boolean value. If set to true, the slim armed player mesh will be used with this skin.

View File

@ -1,12 +1,10 @@
local S = minetest.get_translator("mcl_skins")
local color_to_string = minetest.colorspec_to_colorstring
local EDIT_SKIN_KEY = -1 -- The key used for edit skin in the mcl_skins.simple_skins table
mcl_skins = {
simple_skins = {},
texture_to_simple_skin = {},
item_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"},
tab_names = {"skin", "template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"},
tab_names = {"template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"},
tab_descriptions = {
template = S("Templates"),
arm = S("Arm size"),
@ -20,8 +18,8 @@ mcl_skins = {
headwear = S("Headwears"),
skin = S("Skins"),
},
template1 = {}, -- Stores edit skin values for template1
template2 = {}, -- Stores edit skin values for template2
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
@ -52,89 +50,62 @@ mcl_skins = {
headwear = {},
masks = {},
preview_rotations = {},
ranks = {},
player_skins = {},
player_formspecs = {},
players = {}
}
function mcl_skins.register_item(item)
assert(mcl_skins[item.type], "Skin item type " .. item.type .. " does not exist.")
local texture = item.texture or "blank.png"
if item.template1 then
mcl_skins.template1[item.type] = texture
if item.steve then
mcl_skins.steve[item.type] = texture
end
if item.template2 then
mcl_skins.template2[item.type] = texture
if item.alex then
mcl_skins.alex[item.type] = texture
end
table.insert(mcl_skins[item.type], texture)
mcl_skins.masks[texture] = item.mask
mcl_skins.preview_rotations[texture] = item.preview_rotation
mcl_skins.ranks[texture] = item.rank
end
function mcl_skins.register_simple_skin(skin)
if skin.index then
mcl_skins.simple_skins[skin.index] = skin
else
table.insert(mcl_skins.simple_skins, skin)
if item.preview_rotation then
mcl_skins.preview_rotations[texture] = item.preview_rotation
end
mcl_skins.texture_to_simple_skin[skin.texture] = skin
end
function mcl_skins.save(player)
local skin = mcl_skins.player_skins[player]
local skin = mcl_skins.players[player]
if not skin then return end
local meta = player:get_meta()
meta:set_string("mcl_skins:skin", minetest.serialize(skin))
-- Clear out the old way of storing the simple skin ID
meta:set_string("mcl_skins:skin_id", "")
meta:set_string("mcl_skins:skin_id", tostring(skin.simple_skins_id or ""))
end
minetest.register_chatcommand("skin", {
description = S("Open skin configuration screen."),
privs = {},
func = function(name, param)
local player = minetest.get_player_by_name(name)
local formspec_data = mcl_skins.player_formspecs[player]
local active_tab = formspec_data.active_tab
local page_num = formspec_data.page_num
mcl_skins.show_formspec(player, active_tab, page_num)
end
func = function(name, param) mcl_skins.show_formspec(minetest.get_player_by_name(name)) end
})
function mcl_skins.compile_skin(skin)
if not skin then return "blank.png" end
if skin.simple_skins_id then
return skin.simple_skins_id
return mcl_skins.simple_skins[skin.simple_skins_id].texture
end
local ranks = {}
local layers = {}
for i, item in ipairs(mcl_skins.item_names) do
local texture = skin[item]
local layer = ""
local rank = mcl_skins.ranks[texture] or i * 10
if texture and texture ~= "blank.png" then
if skin[item .. "_color"] and mcl_skins.masks[texture] then
local color = color_to_string(skin[item .. "_color"])
layer = "(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)"
end
if #layer > 0 then layer = layer .. "^" end
layer = layer .. texture
layers[rank] = layer
table.insert(ranks, rank)
end
end
table.sort(ranks)
local output = ""
for i, rank in ipairs(ranks) do
if #output > 0 then output = output .. "^" end
output = output .. layers[rank]
for i, item in pairs(mcl_skins.item_names) do
local texture = skin[item]
if texture and texture ~= "blank.png" then
if skin[item .. "_color"] and mcl_skins.masks[texture] then
if #output > 0 then output = output .. "^" end
local color = color_to_string(skin[item .. "_color"])
output = output ..
"(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)"
end
if #output > 0 then output = output .. "^" end
output = output .. texture
end
end
return output
end
@ -144,13 +115,13 @@ function mcl_skins.update_player_skin(player)
return
end
local skin = mcl_skins.player_skins[player]
local skin = mcl_skins.players[player]
mcl_player.player_set_skin(player, mcl_skins.compile_skin(skin))
local slim_arms
if skin.simple_skins_id then
slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms
slim_arms = mcl_skins.simple_skins[skin.simple_skins_id].slim_arms
else
slim_arms = skin.slim_arms
end
@ -160,35 +131,33 @@ end
-- Load player skin on join
minetest.register_on_joinplayer(function(player)
local function table_get_random(t)
return t[math.random(#t)]
end
local skin = player:get_meta():get_string("mcl_skins:skin")
if skin then
skin = minetest.deserialize(skin)
end
if skin then
if not mcl_skins.texture_to_simple_skin[skin.simple_skins_id] then
skin.simple_skins_id = nil
end
-- If the player moves a slider and then quickly exits the game, form_send_job gets saved.
-- This should never have been put in with the skin data in the first place.
skin.form_send_job = nil
mcl_skins.player_skins[player] = skin
mcl_skins.players[player] = skin
else
if math.random() > 0.5 then
skin = table.copy(mcl_skins.template1)
skin = table.copy(mcl_skins.steve)
else
skin = table.copy(mcl_skins.template2)
skin = table.copy(mcl_skins.alex)
end
mcl_skins.player_skins[player] = skin
mcl_skins.players[player] = skin
end
mcl_skins.player_formspecs[player] = {
active_tab = "skin",
page_num = 1
}
mcl_skins.players[player].simple_skins_id = nil
if #mcl_skins.simple_skins > 0 then
local skin_id = tonumber(player:get_meta():get_string("mcl_skins:skin_id"))
if skin_id and mcl_skins.simple_skins[skin_id] then
local texture = mcl_skins.simple_skins[skin_id].texture
mcl_skins.player_skins[player].simple_skins_id = texture
mcl_skins.players[player].simple_skins_id = skin_id
end
end
mcl_skins.save(player)
@ -196,30 +165,33 @@ minetest.register_on_joinplayer(function(player)
end)
minetest.register_on_leaveplayer(function(player)
mcl_skins.player_skins[player] = nil
mcl_skins.player_formspecs[player] = nil
mcl_skins.players[player] = nil
end)
local function calculate_page_count(tab)
if tab == "skin" then
return math.ceil((#mcl_skins.simple_skins + 2) / 8)
elseif mcl_skins[tab] then
return math.ceil(#mcl_skins[tab] / 16)
end
return 1
end
function mcl_skins.show_formspec(player, active_tab, page_num)
local formspec_data = mcl_skins.player_formspecs[player]
local skin = mcl_skins.player_skins[player]
formspec_data.active_tab = active_tab
local skin = mcl_skins.players[player]
local default = #mcl_skins.simple_skins > 0 and "skin" or "template"
active_tab = active_tab or default
page_num = page_num or 1
local page_count = calculate_page_count(active_tab)
local page_count
if page_num < 1 then page_num = 1 end
if page_num > page_count then page_num = page_count end
formspec_data.page_num = page_num
if mcl_skins[active_tab] then
page_count = math.ceil(#mcl_skins[active_tab] / 16)
if page_num > page_count then
page_num = page_count
end
elseif active_tab == "skin" then
page_count = math.ceil((#mcl_skins.simple_skins + 2) / 8)
if page_num > page_count then
page_num = page_count
end
else
page_num = 1
page_count = 1
end
local formspec = "formspec_version[3]size[14.2,11]"
local formspec = "formspec_version[3]size[13.2,11]"
for i, tab in pairs(mcl_skins.tab_names) do
if tab == active_tab then
@ -229,23 +201,21 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
local y = 0.3 + (i - 1) * 0.8
formspec = formspec ..
"style[" .. tab .. ";content_offset=16,0]" ..
"button[0.3," .. y .. ";4,0.8;" .. tab .. ";" .. mcl_skins.tab_descriptions[tab] .. "]" ..
"image[0.4," .. y + 0.1 .. ";0.6,0.6;mcl_skins_icons.png^[verticalframe:11:" .. i - 1 .. "]"
"button[0.3," .. y .. ";3,0.8;" .. tab .. ";" .. mcl_skins.tab_descriptions[tab] .. "]"
if skin.simple_skins_id then break end
end
local slim_arms
if skin.simple_skins_id then
slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms
slim_arms = mcl_skins.simple_skins[skin.simple_skins_id].slim_arms
else
slim_arms = skin.slim_arms
end
local mesh = slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d"
formspec = formspec ..
"model[11,0.3;3,7;player_mesh;" .. mesh .. ";" ..
"model[10,0.3;3,7;player_mesh;" .. mesh .. ";" ..
mcl_skins.compile_skin(skin) ..
",blank.png,blank.png;0,180;false;true;0,0]"
@ -254,24 +224,23 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
local page_end = math.min(page_start + 8 - 1, #mcl_skins.simple_skins)
formspec = formspec ..
"style_type[button;bgcolor=#00000000]"
local skin = table.copy(skin)
local simple_skins_id = skin.simple_skins_id
local skin_id = skin.simple_skins_id or -1
skin.simple_skins_id = nil
mcl_skins.simple_skins[EDIT_SKIN_KEY] = {
local skins = table.copy(mcl_skins.simple_skins)
skins[-1] = {
slim_arms = skin.slim_arms,
texture = mcl_skins.compile_skin(skin),
}
simple_skins_id = simple_skins_id or
mcl_skins.simple_skins[EDIT_SKIN_KEY].texture
for i = page_start, page_end do
local skin = mcl_skins.simple_skins[i]
local skin = skins[i]
local j = i - page_start - 1
local mesh = skin.slim_arms and "mcl_armor_character_female.b3d" or
"mcl_armor_character.b3d"
local mesh = skin.slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d"
local x = 4.5 + (j + 1) % 4 * 1.6
local x = 3.5 + (j + 1) % 4 * 1.6
local y = 0.3 + math.floor((j + 1) / 4) * 3.1
formspec = formspec ..
@ -279,7 +248,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
skin.texture ..
",blank.png,blank.png;0,180;false;true;0,0]"
if simple_skins_id == skin.texture then
if skin_id == i then
formspec = formspec ..
"style[" .. i ..
";bgcolor=;bgimg=mcl_skins_select_overlay.png;" ..
@ -289,22 +258,22 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
"button[" .. x .. "," .. y .. ";1.5,3;" .. i .. ";]"
end
if page_start == EDIT_SKIN_KEY then
formspec = formspec .. "image[4.85,1;0.8,0.8;mcl_skins_button.png]"
if page_start == -1 then
formspec = formspec .. "image[3.85,1;0.8,0.8;mcl_skins_button.png]"
end
elseif active_tab == "template" then
formspec = formspec ..
"model[5,2;2,3;player_mesh;mcl_armor_character.b3d;" ..
mcl_skins.compile_skin(mcl_skins.template1) ..
"model[4,2;2,3;player_mesh;mcl_armor_character.b3d;" ..
mcl_skins.compile_skin(mcl_skins.steve) ..
",blank.png,blank.png;0,180;false;true;0,0]" ..
"button[5,5.2;2,0.8;template1;" .. S("Select") .. "]" ..
"button[4,5.2;2,0.8;steve;" .. S("Select") .. "]" ..
"model[7.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" ..
mcl_skins.compile_skin(mcl_skins.template2) ..
"model[6.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" ..
mcl_skins.compile_skin(mcl_skins.alex) ..
",blank.png,blank.png;0,180;false;true;0,0]" ..
"button[7.5,5.2;2,0.8;template2;" .. S("Select") .. "]"
"button[6.5,5.2;2,0.8;alex;" .. S("Select") .. "]"
elseif mcl_skins[active_tab] then
formspec = formspec ..
@ -339,7 +308,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
end
i = i - 1
local x = 4.5 + i % 4 * 1.6
local x = 3.5 + i % 4 * 1.6
local y = 0.3 + math.floor(i / 4) * 1.6
formspec = formspec ..
"model[" .. x .. "," .. y ..
@ -356,12 +325,11 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
formspec = formspec .. "button[" .. x .. "," .. y .. ";1.5,1.5;" .. texture .. ";]"
end
elseif active_tab == "arm" then
local x = skin.slim_arms and 5.7 or 4.6
local x = skin.slim_arms and 4.7 or 3.6
formspec = formspec ..
"image_button[4.6,0.3;1,1;mcl_skins_thick_arms.png;thick_arms;]" ..
"image_button[5.7,0.3;1,1;mcl_skins_slim_arms.png;slim_arms;]" ..
"style[arm;bgcolor=;bgimg=mcl_skins_select_overlay.png;" ..
"bgimg_middle=14,14;bgimg_pressed=mcl_skins_select_overlay.png]" ..
"image_button[3.6,0.3;1,1;mcl_skins_thick_arms.png;thick_arms;]" ..
"image_button[4.7,0.3;1,1;mcl_skins_slim_arms.png;slim_arms;]" ..
"style[arm;bgcolor=;bgimg=mcl_skins_select_overlay.png;bgimg_middle=14,14;bgimg_pressed=mcl_skins_select_overlay.png]" ..
"button[" .. x .. ",0.3;1,1;arm;]"
end
@ -375,7 +343,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
for i, colorspec in pairs(colors) do
local color = color_to_string(colorspec)
i = i - 1
local x = 4.6 + i % 6 * 0.9
local x = 3.6 + i % 6 * 0.9
local y = 8 + math.floor(i / 6) * 0.9
formspec = formspec ..
"image_button[" .. x .. "," .. y ..
@ -385,8 +353,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
if selected_color == colorspec then
formspec = formspec ..
"style[" .. color ..
";bgcolor=;bgimg=mcl_skins_select_overlay.png;bgimg_middle=14,14;" ..
"bgimg_pressed=mcl_skins_select_overlay.png]" ..
";bgcolor=;bgimg=mcl_skins_select_overlay.png;bgimg_middle=14,14;bgimg_pressed=mcl_skins_select_overlay.png]" ..
"button[" .. x .. "," .. y .. ";0.8,0.8;" .. color .. ";]"
end
@ -398,7 +365,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
local green = math.floor(selected_color / 0x100) - 0xff0000 - red * 0x100
local blue = selected_color - 0xff000000 - red * 0x10000 - green * 0x100
formspec = formspec ..
"container[10.2,8]" ..
"container[9.2,8]" ..
"scrollbaroptions[min=0;max=255;smallstep=20]" ..
"box[0.4,0;2.49,0.38;red]" ..
@ -419,42 +386,49 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
"container_end[]"
end
end
if page_num > 1 then
formspec = formspec ..
"image_button[4.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]"
"image_button[3.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]"
end
if page_num < page_count then
formspec = formspec ..
"image_button[9.8,6.7;1,1;mcl_skins_arrow.png;next_page;]"
"image_button[8.8,6.7;1,1;mcl_skins_arrow.png;next_page;]"
end
if page_count > 1 then
formspec = formspec ..
"label[7.3,7.2;" .. page_num .. " / " .. page_count .. "]"
"label[6.3,7.2;" .. page_num .. " / " .. page_count .. "]"
end
local player_name = player:get_player_name()
minetest.show_formspec(player_name, "mcl_skins:skins", formspec)
minetest.show_formspec(player_name, "mcl_skins:" .. active_tab .. "_" .. page_num, formspec)
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
local formspec_data = mcl_skins.player_formspecs[player]
local active_tab = formspec_data.active_tab
local page_num = formspec_data.page_num
if fields.__mcl_skins then
mcl_skins.show_formspec(player, active_tab, page_num)
mcl_skins.show_formspec(player)
return false
end
if formname ~= "mcl_skins:skins" then return false end
if not formname:find("^mcl_skins:") then return false end
local _, _, active_tab, page_num = formname:find("^mcl_skins:(%a+)_(%d+)")
local active_tab_found = false
for _, tab in pairs(mcl_skins.tab_names) do
if tab == active_tab then active_tab_found = true end
end
active_tab = active_tab_found and active_tab or "template"
if not page_num or not active_tab then return true end
page_num = math.floor(tonumber(page_num) or 1)
-- Cancel formspec resend after scrollbar move
if formspec_data.form_send_job then
formspec_data.form_send_job:cancel()
formspec_data.form_send_job = nil
if mcl_skins.players[player].form_send_job then
mcl_skins.players[player].form_send_job:cancel()
mcl_skins.players[player].form_send_job = nil
end
if fields.quit then
@ -462,13 +436,13 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
return true
end
if fields.template2 then
mcl_skins.player_skins[player] = table.copy(mcl_skins.template2)
if fields.alex then
mcl_skins.players[player] = table.copy(mcl_skins.alex)
mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num)
return true
elseif fields.template1 then
mcl_skins.player_skins[player] = table.copy(mcl_skins.template1)
elseif fields.steve then
mcl_skins.players[player] = table.copy(mcl_skins.steve)
mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num)
return true
@ -476,12 +450,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
for i, tab in pairs(mcl_skins.tab_names) do
if fields[tab] then
mcl_skins.show_formspec(player, tab, 1)
mcl_skins.show_formspec(player, tab, page_num)
return true
end
end
local skin = mcl_skins.player_skins[player]
local skin = mcl_skins.players[player]
if not skin then return true end
if fields.next_page then
@ -522,12 +496,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local color = 0xff000000 + red * 0x10000 + green * 0x100 + blue
if color >= 0 and color <= 0xffffffff then
-- We delay resedning the form because otherwise it will break dragging scrollbars
formspec_data.form_send_job = minetest.after(0.2, function()
mcl_skins.players[player].form_send_job = minetest.after(0.2, function()
if player and player:is_player() then
skin[active_tab .. "_color"] = color
mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num)
formspec_data.form_send_job = nil
mcl_skins.players[player].form_send_job = nil
end
end)
return true
@ -543,14 +517,14 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
if field and active_tab == "skin" then
local index = tonumber(field)
index = index and math.floor(index) or 0
mcl_skins.simple_skins[EDIT_SKIN_KEY].texture = nil
local skin_id = tonumber(field)
skin_id = skin_id and math.floor(skin_id) or 0
if
#mcl_skins.simple_skins > 0 and
index >= EDIT_SKIN_KEY and index <= #mcl_skins.simple_skins
skin_id >= -1 and skin_id <= #mcl_skins.simple_skins
then
skin.simple_skins_id = mcl_skins.simple_skins[index].texture
if skin_id == -1 then skin_id = nil end
skin.simple_skins_id = skin_id
mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num)
end
@ -558,14 +532,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
-- See if field is a texture
if
field and mcl_skins[active_tab] and
table.indexof(mcl_skins[active_tab], field) ~= -1
then
skin[active_tab] = field
mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num)
return true
if field and mcl_skins[active_tab] then
for i, texture in pairs(mcl_skins[active_tab]) do
if texture == field then
skin[active_tab] = texture
mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num)
return true
end
end
end
-- See if field is a color
@ -584,6 +559,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end)
local function init()
local function file_exists(name)
local f = io.open(name)
if not f then
return false
end
f:close()
return true
end
local f = io.open(minetest.get_modpath("mcl_skins") .. "/list.json")
assert(f, "Can't open the file list.json")
local data = f:read("*all")
@ -595,27 +579,17 @@ local function init()
for _, item in pairs(json) do
mcl_skins.register_item(item)
end
mcl_skins.template1.base_color = mcl_skins.base_color[2]
mcl_skins.template1.hair_color = 0xff5d473b
mcl_skins.template1.top_color = 0xff993535
mcl_skins.template1.bottom_color = 0xff644939
mcl_skins.template1.slim_arms = false
mcl_skins.steve.base_color = mcl_skins.base_color[2]
mcl_skins.steve.hair_color = 0xff5d473b
mcl_skins.steve.top_color = 0xff993535
mcl_skins.steve.bottom_color = 0xff644939
mcl_skins.steve.slim_arms = false
mcl_skins.template2.base_color = mcl_skins.base_color[1]
mcl_skins.template2.hair_color = 0xff715d57
mcl_skins.template2.top_color = 0xff346840
mcl_skins.template2.bottom_color = 0xff383532
mcl_skins.template2.slim_arms = true
mcl_skins.register_simple_skin({
index = 0,
texture = "character.png"
})
mcl_skins.register_simple_skin({
index = 1,
texture = "mcl_skins_character_1.png",
slim_arms = true
})
mcl_skins.alex.base_color = mcl_skins.base_color[1]
mcl_skins.alex.hair_color = 0xff715d57
mcl_skins.alex.top_color = 0xff346840
mcl_skins.alex.bottom_color = 0xff383532
mcl_skins.alex.slim_arms = true
end
init()

View File

@ -2,9 +2,8 @@
{
"type": "footwear",
"texture": "mcl_skins_footwear_1.png",
"template1": true,
"template2": true,
"rank": 55
"steve": true,
"alex": true
},
{
"type": "footwear",
@ -20,12 +19,12 @@
{
"type": "eye",
"texture": "mcl_skins_eye_1.png",
"template2": true
"alex": true
},
{
"type": "eye",
"texture": "mcl_skins_eye_2.png",
"template1": true
"steve": true
},
{
"type": "eye",
@ -50,7 +49,7 @@
{
"type": "mouth",
"texture": "mcl_skins_mouth_1.png",
"template1": true
"steve": true
},
{
"type": "mouth",
@ -78,19 +77,19 @@
},
{
"type": "mouth",
"template1": true
"alex": true
},
{
"type": "hair",
"texture": "mcl_skins_hair_1.png",
"mask": "mcl_skins_hair_1_mask.png",
"template2": true
"alex": true
},
{
"type": "hair",
"texture": "mcl_skins_hair_2.png",
"mask": "mcl_skins_hair_2_mask.png",
"template1": true
"steve": true
},
{
"type": "hair",
@ -147,7 +146,7 @@
{
"type": "headwear",
"texture": "mcl_skins_headwear_2.png",
"template2": true
"alex": true
},
{
"type": "headwear",
@ -175,14 +174,14 @@
},
{
"type": "headwear",
"template1": true
"steve": true
},
{
"type": "bottom",
"texture": "mcl_skins_bottom_1.png",
"mask": "mcl_skins_bottom_1_mask.png",
"template1": true,
"template2": true
"steve": true,
"alex": true
},
{
"type": "bottom",
@ -199,18 +198,12 @@
"texture": "mcl_skins_bottom_4.png",
"mask": "mcl_skins_bottom_4_mask.png"
},
{
"type": "bottom",
"texture": "mcl_skins_bottom_5.png",
"mask": "mcl_skins_bottom_5_mask.png",
"rank": 65
},
{
"type": "top",
"texture": "mcl_skins_top_1.png",
"mask": "mcl_skins_top_1_mask.png",
"template1": true,
"template2": true
"steve": true,
"alex": true
},
{
"type": "top",
@ -261,7 +254,7 @@
"type": "base",
"texture": "mcl_skins_base_1.png",
"mask": "mcl_skins_base_1_mask.png",
"template1": true,
"template2": true
"steve": true,
"alex": true
}
]

View File

@ -21,9 +21,6 @@ mcl_skins_bottom_3.png
mcl_skins_eye_7.png
mcl_skins_mouth_7.png
mcl_skins_hair_10.png
mcl_skins_hair_6.png
mcl_skins_eye_6.png
mcl_skins_bottom_5.png
Original work by MrRar
License: CC BY-SA 4.0
@ -69,6 +66,13 @@ 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

View File

@ -14,9 +14,7 @@ function mcl_skins.get_skin_list()
for _, game_mode in pairs({"_crea", "_surv"}) do
for _, base in pairs(mcl_skins.base) do
for _, base_color in pairs(mcl_skins.base_color) do
local id = base:gsub(".png$", "")
.. minetest.colorspec_to_colorstring(base_color):gsub("#", "")
local id = base:gsub(".png$", "") .. minetest.colorspec_to_colorstring(base_color):gsub("#", "")
local female = {
texture = make_texture(base, base_color),
slim_arms = true,
@ -38,8 +36,7 @@ function mcl_skins.get_skin_list()
table.insert(list, {
texture = skin.texture,
slim_arms = skin.slim_arms,
id = skin.texture:gsub(".png$", "")
.. (skin.slim_arms and "_female" or "_male") .. game_mode,
id = skin.texture:gsub(".png$", "") .. (skin.slim_arms and "_female" or "_male") .. game_mode,
creative = game_mode == "_crea"
})
end
@ -48,10 +45,10 @@ function mcl_skins.get_skin_list()
end
function mcl_skins.get_node_id_by_player(player)
local skin = mcl_skins.player_skins[player]
local skin = mcl_skins.players[player]
local simple_skin = skin.simple_skins_id
if simple_skin then
skin = mcl_skins.texture_to_simple_skin[skin.simple_skins_id]
skin = mcl_skins.simple_skins[skin.simple_skins_id]
end
local creative = minetest.is_creative_enabled(player:get_player_name())
local append = (skin.slim_arms and "_female" or "_male") .. (creative and "_crea" or "_surv")

View File

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

View File

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

View File

@ -1,5 +1,5 @@
local function init_simple_skins()
local id, f, data, skin = 2
local id, f, data, skin = 0
local mod_path = minetest.get_modpath("mcl_skins")
while true do
@ -35,13 +35,18 @@ local function init_simple_skins()
end
-- add metadata to list
mcl_skins.register_simple_skin({
index = id,
mcl_skins.simple_skins[id] = {
texture = skin,
slim_arms = data and data.gender == "female",
})
}
id = id + 1
end
if #mcl_skins.simple_skins > 0 then
table.insert(mcl_skins.tab_names, 1, "skin")
else
mcl_skins.simple_skins = {}
end
end
init_simple_skins()

View File

@ -1,3 +0,0 @@
To add custom skins to the game, please use the mcl_custom_skins mod.
Download it from https://git.minetest.land/mineclone2/mcl_custom_skins
Support for adding custom skins to mcl_skins will be removed in a future MineClone2 release.

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 B

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 749 B

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 B

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 B

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 535 B

After

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 B

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 B

After

Width:  |  Height:  |  Size: 124 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 B

After

Width:  |  Height:  |  Size: 122 B