Compare commits

...

11 Commits

Author SHA1 Message Date
Lars Mueller b866d5d98e Fix texture modifiers relying on undocumented behavior 2023-05-27 17:27:01 +02:00
ancientmarinerdev 019717cab0 Merge pull request 'Add support for external custom skins mod' (#3653) from skins into master
Reviewed-on: MineClone2/MineClone2#3653
Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
2023-05-26 20:55:53 +00:00
𝕵𝖔𝖍𝖆𝖓𝖓𝖊𝖘 𝕱𝖗𝖎𝖙𝖟 f1d17e2c69 mcl_skins: PR feedback 2023-05-26 20:27:11 +00:00
𝕵𝖔𝖍𝖆𝖓𝖓𝖊𝖘 𝕱𝖗𝖎𝖙𝖟 26f033932e Add mcl_custom_skins info to README 2023-05-26 20:27:11 +00:00
𝕵𝖔𝖍𝖆𝖓𝖓𝖊𝖘 𝕱𝖗𝖎𝖙𝖟 1e63f3931a Skins update 2023-05-26 20:27:11 +00:00
ancientmarinerdev bd37ed178c Merge pull request 'Fix pig riding' (#3675) from fix_pig_riding into master
Reviewed-on: MineClone2/MineClone2#3675
Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
2023-05-22 21:47:14 +00:00
PrairieWind 5ed92a2695 Make pigs mountable without carrot on a stick, but require the carrot on a stick to actually control the pig 2023-05-22 21:40:23 +00:00
ancientmarinerdev 8f60fb08d3 Merge pull request 'Fix global variable references and exit mob_step if missing pos' (#3741) from mobs_tweaks into master
Reviewed-on: MineClone2/MineClone2#3741
2023-05-22 21:12:43 +00:00
ancientmarinerdev 10a3d06360 Fix global variable references and exit mob_step if missing pos 2023-05-22 21:05:12 +00:00
ancientmarinerdev 08cbd95a5e Merge pull request 'Make sure dying sign text respects protection' (#3727) from sign_dye_protection into master
Reviewed-on: MineClone2/MineClone2#3727
Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
2023-05-22 20:53:58 +00:00
PrairieWind a5a035d9bb Make sure dying sign text respects protection 2023-05-22 20:47:49 +00:00
38 changed files with 330 additions and 257 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)
local function who_are_you_looking_at (self, dtime)
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)
who_are_you_looking_at (self, dtime)
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 end -- mcl_burning.tick may remove object immediately
if not self.object:get_pos() then return true 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 then
if self.driver and self.driver:get_wielded_item():get_name() == "mcl_mobitems:carrot_on_a_stick" then
mcl_mobs.drive(self, "walk", "stand", false, dtime)
@ -149,18 +149,14 @@ mcl_mobs.register_mob("mobs_mc:pig", {
return
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)
-- 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
if not minetest.is_creative_enabled(clicker:get_player_name()) then
local inv = self.driver:get_inventory()
@ -177,6 +173,19 @@ 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
@ -195,6 +204,18 @@ 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

@ -158,8 +158,10 @@ 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

@ -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=node_pos, gain=0.5, max_hear_distance=16}, true)
minetest.sound_play({name="mcl_barrels_default_barrel_open", pos=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=node_pos, gain=0.5, max_hear_distance=16}, true)
minetest.sound_play({name="mcl_barrels_default_barrel_close", pos=pos, gain=0.5, max_hear_distance=16}, true)
end
end

View File

@ -89,7 +89,7 @@ local function get_beacon_beam(glass_nodename)
end
minetest.register_node("mcl_beacons:beacon_beam", {
tiles = {"^[colorize:#b8bab9"},
tiles = {"blank.png^[noalpha^[colorize:#b8bab9"},
drawtype = "nodebox",
node_box = {
type = "fixed",

View File

@ -370,7 +370,7 @@ minetest.register_node("mcl_core:dirt_with_grass", {
_doc_items_hidden = false,
paramtype2 = "color",
tiles = {"mcl_core_grass_block_top.png", { name="default_dirt.png", color="white" }, { name="default_dirt.png^mcl_dirt_grass_shadow.png", color="white" }},
overlay_tiles = {"mcl_core_grass_block_top.png", "", {name="mcl_core_grass_block_side_overlay.png", tileable_vertical=false}},
overlay_tiles = {"mcl_core_grass_block_top.png", "blank.png", {name="mcl_core_grass_block_side_overlay.png", tileable_vertical=false}},
palette = "mcl_core_palette_grass.png",
palette_index = 0,
color = "#7CBD6B",

View File

@ -314,18 +314,18 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
"blank.png", -- right
"blank.png", -- left
connected_stem_texture, -- back
connected_stem_texture .. "^[transformFX90" --front
connected_stem_texture .. "^[transformFX" --front
},
{ "blank.png", --top
"blank.png", -- bottom
"blank.png", -- right
"blank.png", -- left
connected_stem_texture .. "^[transformFX90", --back
connected_stem_texture .. "^[transformFX", --back
connected_stem_texture, -- front
},
{ "blank.png", --top
"blank.png", -- bottom
connected_stem_texture .. "^[transformFX90", -- right
connected_stem_texture .. "^[transformFX", -- right
connected_stem_texture, -- left
"blank.png", --back
"blank.png", -- front
@ -333,7 +333,7 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
{ "blank.png", --top
"blank.png", -- bottom
connected_stem_texture, -- right
connected_stem_texture .. "^[transformFX90", -- left
connected_stem_texture .. "^[transformFX", -- left
"blank.png", --back
"blank.png", -- front
}

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
depends = mcl_core, mcl_sounds, mcl_dye, mcl_colors, mcl_util
optional_depends = doc

View File

@ -307,7 +307,9 @@ mcl_signs.wall_standard = {
local item = clicker:get_wielded_item()
local iname = item:get_name()
if node then
local protected = mcl_util.check_position_protection(pos, clicker)
if node and not protected then
if DEBUG then
minetest.log("verbose", "[mcl_signs] Wall_Sign Right Click event on valid node.")
end
@ -414,7 +416,9 @@ mcl_signs.standing_standard = {
local item = clicker:get_wielded_item()
local iname = item:get_name()
if node then
local protected = mcl_util.check_position_protection(pos, clicker)
if node and not protected 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,biomemap,nodes)
local function set_seagrass_param2(minp,maxp,data2,area,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,biomemap,{"group:seagrass"})
lvm_used = set_seagrass_param2(minp, maxp, data2, area, {"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
optional_depends = mcl_skins, mcl_custom_skins

View File

@ -28,28 +28,6 @@ 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 = {}
@ -112,6 +90,7 @@ 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",
@ -119,14 +98,20 @@ function mcl_player.player_set_model(player, model_name)
damage_texture_modifier = "^[colorize:red:130",
})
update_player_textures(player)
mcl_player.player_set_animation(player, "stand")
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)
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)
@ -180,7 +165,6 @@ 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>>>>

View File

@ -3,9 +3,11 @@
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: TenPlus1, Zeg9, MrRar
Author: MrRar
See image_credits.txt for image licensing.
@ -15,6 +17,7 @@ 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"
@ -28,16 +31,40 @@ Coloring only works for "base", "bottom, "top", and "hair".
`preview_rotation`
A table containing properties x and y. x and y represent the x and y rotation of the item preview.
`alex`
If set to true the item will be default for female character.
`template2`
If set to true the item will be default for female template.
`steve`
If set to true the item will be default for male 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.
### `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"
@ -50,7 +77,9 @@ 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)`
@ -71,10 +100,19 @@ 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.players`
### `mcl_skins.player_skins`
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,10 +1,12 @@
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 = {"template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"},
tab_names = {"skin", "template", "base", "headwear", "hair", "eye", "mouth", "top", "arm", "bottom", "footwear"},
tab_descriptions = {
template = S("Templates"),
arm = S("Arm size"),
@ -18,8 +20,8 @@ mcl_skins = {
headwear = S("Headwears"),
skin = S("Skins"),
},
steve = {}, -- Stores skin values for Steve skin
alex = {}, -- Stores skin values for Alex skin
template1 = {}, -- Stores edit skin values for template1
template2 = {}, -- Stores edit skin values for template2
base = {}, -- List of base textures
-- Base color is separate to keep the number of junk nodes registered in check
@ -50,62 +52,89 @@ mcl_skins = {
headwear = {},
masks = {},
preview_rotations = {},
players = {}
ranks = {},
player_skins = {},
player_formspecs = {},
}
function mcl_skins.register_item(item)
assert(mcl_skins[item.type], "Skin item type " .. item.type .. " does not exist.")
local texture = item.texture or "blank.png"
if item.steve then
mcl_skins.steve[item.type] = texture
if item.template1 then
mcl_skins.template1[item.type] = texture
end
if item.alex then
mcl_skins.alex[item.type] = texture
if item.template2 then
mcl_skins.template2[item.type] = texture
end
table.insert(mcl_skins[item.type], texture)
mcl_skins.masks[texture] = item.mask
if item.preview_rotation then
mcl_skins.preview_rotations[texture] = item.preview_rotation
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)
end
mcl_skins.texture_to_simple_skin[skin.texture] = skin
end
function mcl_skins.save(player)
local skin = mcl_skins.players[player]
local skin = mcl_skins.player_skins[player]
if not skin then return end
local meta = player:get_meta()
meta:set_string("mcl_skins:skin", minetest.serialize(skin))
meta:set_string("mcl_skins:skin_id", tostring(skin.simple_skins_id or ""))
-- Clear out the old way of storing the simple skin ID
meta:set_string("mcl_skins:skin_id", "")
end
minetest.register_chatcommand("skin", {
description = S("Open skin configuration screen."),
privs = {},
func = function(name, param) mcl_skins.show_formspec(minetest.get_player_by_name(name)) end
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
})
function mcl_skins.compile_skin(skin)
if not skin then return "blank.png" end
if skin.simple_skins_id then
return mcl_skins.simple_skins[skin.simple_skins_id].texture
return skin.simple_skins_id
end
local output = ""
for i, item in pairs(mcl_skins.item_names) do
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
if #output > 0 then output = output .. "^" end
local color = color_to_string(skin[item .. "_color"])
output = output ..
"(" .. mcl_skins.masks[texture] .. "^[colorize:" .. color .. ":alpha)"
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 .. texture
end
output = output .. layers[rank]
end
return output
end
@ -115,13 +144,13 @@ function mcl_skins.update_player_skin(player)
return
end
local skin = mcl_skins.players[player]
local skin = mcl_skins.player_skins[player]
mcl_player.player_set_skin(player, mcl_skins.compile_skin(skin))
local slim_arms
if skin.simple_skins_id then
slim_arms = mcl_skins.simple_skins[skin.simple_skins_id].slim_arms
slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms
else
slim_arms = skin.slim_arms
end
@ -131,33 +160,35 @@ 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 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
if not mcl_skins.texture_to_simple_skin[skin.simple_skins_id] then
skin.simple_skins_id = nil
end
mcl_skins.players[player] = skin
mcl_skins.player_skins[player] = skin
else
if math.random() > 0.5 then
skin = table.copy(mcl_skins.steve)
skin = table.copy(mcl_skins.template1)
else
skin = table.copy(mcl_skins.alex)
skin = table.copy(mcl_skins.template2)
end
mcl_skins.players[player] = skin
mcl_skins.player_skins[player] = skin
end
mcl_skins.players[player].simple_skins_id = nil
mcl_skins.player_formspecs[player] = {
active_tab = "skin",
page_num = 1
}
if #mcl_skins.simple_skins > 0 then
local skin_id = tonumber(player:get_meta():get_string("mcl_skins:skin_id"))
if skin_id and mcl_skins.simple_skins[skin_id] then
mcl_skins.players[player].simple_skins_id = skin_id
local texture = mcl_skins.simple_skins[skin_id].texture
mcl_skins.player_skins[player].simple_skins_id = texture
end
end
mcl_skins.save(player)
@ -165,33 +196,30 @@ minetest.register_on_joinplayer(function(player)
end)
minetest.register_on_leaveplayer(function(player)
mcl_skins.players[player] = nil
mcl_skins.player_skins[player] = nil
mcl_skins.player_formspecs[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 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 formspec_data = mcl_skins.player_formspecs[player]
local skin = mcl_skins.player_skins[player]
formspec_data.active_tab = active_tab
local page_count
local page_count = calculate_page_count(active_tab)
if page_num < 1 then page_num = 1 end
if mcl_skins[active_tab] then
page_count = math.ceil(#mcl_skins[active_tab] / 16)
if page_num > page_count then
page_num = page_count
end
elseif active_tab == "skin" then
page_count = math.ceil((#mcl_skins.simple_skins + 2) / 8)
if page_num > page_count then
page_num = page_count
end
else
page_num = 1
page_count = 1
end
if page_num > page_count then page_num = page_count end
formspec_data.page_num = page_num
local formspec = "formspec_version[3]size[13.2,11]"
local formspec = "formspec_version[3]size[14.2,11]"
for i, tab in pairs(mcl_skins.tab_names) do
if tab == active_tab then
@ -201,21 +229,23 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
local y = 0.3 + (i - 1) * 0.8
formspec = formspec ..
"button[0.3," .. y .. ";3,0.8;" .. tab .. ";" .. mcl_skins.tab_descriptions[tab] .. "]"
"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 .. "]"
if skin.simple_skins_id then break end
end
local slim_arms
if skin.simple_skins_id then
slim_arms = mcl_skins.simple_skins[skin.simple_skins_id].slim_arms
slim_arms = mcl_skins.texture_to_simple_skin[skin.simple_skins_id].slim_arms
else
slim_arms = skin.slim_arms
end
local mesh = slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d"
formspec = formspec ..
"model[10,0.3;3,7;player_mesh;" .. mesh .. ";" ..
"model[11,0.3;3,7;player_mesh;" .. mesh .. ";" ..
mcl_skins.compile_skin(skin) ..
",blank.png,blank.png;0,180;false;true;0,0]"
@ -226,21 +256,22 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
"style_type[button;bgcolor=#00000000]"
local skin = table.copy(skin)
local skin_id = skin.simple_skins_id or -1
local simple_skins_id = skin.simple_skins_id
skin.simple_skins_id = nil
local skins = table.copy(mcl_skins.simple_skins)
skins[-1] = {
mcl_skins.simple_skins[EDIT_SKIN_KEY] = {
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 = skins[i]
local skin = mcl_skins.simple_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 = 3.5 + (j + 1) % 4 * 1.6
local x = 4.5 + (j + 1) % 4 * 1.6
local y = 0.3 + math.floor((j + 1) / 4) * 3.1
formspec = formspec ..
@ -248,7 +279,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
skin.texture ..
",blank.png,blank.png;0,180;false;true;0,0]"
if skin_id == i then
if simple_skins_id == skin.texture then
formspec = formspec ..
"style[" .. i ..
";bgcolor=;bgimg=mcl_skins_select_overlay.png;" ..
@ -258,22 +289,22 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
"button[" .. x .. "," .. y .. ";1.5,3;" .. i .. ";]"
end
if page_start == -1 then
formspec = formspec .. "image[3.85,1;0.8,0.8;mcl_skins_button.png]"
if page_start == EDIT_SKIN_KEY then
formspec = formspec .. "image[4.85,1;0.8,0.8;mcl_skins_button.png]"
end
elseif active_tab == "template" then
formspec = formspec ..
"model[4,2;2,3;player_mesh;mcl_armor_character.b3d;" ..
mcl_skins.compile_skin(mcl_skins.steve) ..
"model[5,2;2,3;player_mesh;mcl_armor_character.b3d;" ..
mcl_skins.compile_skin(mcl_skins.template1) ..
",blank.png,blank.png;0,180;false;true;0,0]" ..
"button[4,5.2;2,0.8;steve;" .. S("Select") .. "]" ..
"button[5,5.2;2,0.8;template1;" .. S("Select") .. "]" ..
"model[6.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" ..
mcl_skins.compile_skin(mcl_skins.alex) ..
"model[7.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" ..
mcl_skins.compile_skin(mcl_skins.template2) ..
",blank.png,blank.png;0,180;false;true;0,0]" ..
"button[6.5,5.2;2,0.8;alex;" .. S("Select") .. "]"
"button[7.5,5.2;2,0.8;template2;" .. S("Select") .. "]"
elseif mcl_skins[active_tab] then
formspec = formspec ..
@ -308,7 +339,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
end
i = i - 1
local x = 3.5 + i % 4 * 1.6
local x = 4.5 + i % 4 * 1.6
local y = 0.3 + math.floor(i / 4) * 1.6
formspec = formspec ..
"model[" .. x .. "," .. y ..
@ -325,11 +356,12 @@ 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 4.7 or 3.6
local x = skin.slim_arms and 5.7 or 4.6
formspec = formspec ..
"image_button[3.6,0.3;1,1;mcl_skins_thick_arms.png;thick_arms;]" ..
"image_button[4.7,0.3;1,1;mcl_skins_slim_arms.png;slim_arms;]" ..
"style[arm;bgcolor=;bgimg=mcl_skins_select_overlay.png;bgimg_middle=14,14;bgimg_pressed=mcl_skins_select_overlay.png]" ..
"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]" ..
"button[" .. x .. ",0.3;1,1;arm;]"
end
@ -343,7 +375,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 = 3.6 + i % 6 * 0.9
local x = 4.6 + i % 6 * 0.9
local y = 8 + math.floor(i / 6) * 0.9
formspec = formspec ..
"image_button[" .. x .. "," .. y ..
@ -353,7 +385,8 @@ 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
@ -365,7 +398,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[9.2,8]" ..
"container[10.2,8]" ..
"scrollbaroptions[min=0;max=255;smallstep=20]" ..
"box[0.4,0;2.49,0.38;red]" ..
@ -389,46 +422,39 @@ function mcl_skins.show_formspec(player, active_tab, page_num)
if page_num > 1 then
formspec = formspec ..
"image_button[3.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]"
"image_button[4.5,6.7;1,1;mcl_skins_arrow.png^[transformFX;previous_page;]"
end
if page_num < page_count then
formspec = formspec ..
"image_button[8.8,6.7;1,1;mcl_skins_arrow.png;next_page;]"
"image_button[9.8,6.7;1,1;mcl_skins_arrow.png;next_page;]"
end
if page_count > 1 then
formspec = formspec ..
"label[6.3,7.2;" .. page_num .. " / " .. page_count .. "]"
"label[7.3,7.2;" .. page_num .. " / " .. page_count .. "]"
end
local player_name = player:get_player_name()
minetest.show_formspec(player_name, "mcl_skins:" .. active_tab .. "_" .. page_num, formspec)
minetest.show_formspec(player_name, "mcl_skins:skins", 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)
mcl_skins.show_formspec(player, active_tab, page_num)
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)
if formname ~= "mcl_skins:skins" then return false end
-- Cancel formspec resend after scrollbar move
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
if formspec_data.form_send_job then
formspec_data.form_send_job:cancel()
formspec_data.form_send_job = nil
end
if fields.quit then
@ -436,13 +462,13 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
return true
end
if fields.alex then
mcl_skins.players[player] = table.copy(mcl_skins.alex)
if fields.template2 then
mcl_skins.player_skins[player] = table.copy(mcl_skins.template2)
mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num)
return true
elseif fields.steve then
mcl_skins.players[player] = table.copy(mcl_skins.steve)
elseif fields.template1 then
mcl_skins.player_skins[player] = table.copy(mcl_skins.template1)
mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num)
return true
@ -450,12 +476,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, page_num)
mcl_skins.show_formspec(player, tab, 1)
return true
end
end
local skin = mcl_skins.players[player]
local skin = mcl_skins.player_skins[player]
if not skin then return true end
if fields.next_page then
@ -496,12 +522,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local color = 0xff000000 + red * 0x10000 + green * 0x100 + blue
if color >= 0 and color <= 0xffffffff then
-- We delay resedning the form because otherwise it will break dragging scrollbars
mcl_skins.players[player].form_send_job = minetest.after(0.2, function()
formspec_data.form_send_job = minetest.after(0.2, function()
if player and player:is_player() then
skin[active_tab .. "_color"] = color
mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num)
mcl_skins.players[player].form_send_job = nil
formspec_data.form_send_job = nil
end
end)
return true
@ -517,14 +543,14 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
if field and active_tab == "skin" then
local skin_id = tonumber(field)
skin_id = skin_id and math.floor(skin_id) or 0
local index = tonumber(field)
index = index and math.floor(index) or 0
mcl_skins.simple_skins[EDIT_SKIN_KEY].texture = nil
if
#mcl_skins.simple_skins > 0 and
skin_id >= -1 and skin_id <= #mcl_skins.simple_skins
index >= EDIT_SKIN_KEY and index <= #mcl_skins.simple_skins
then
if skin_id == -1 then skin_id = nil end
skin.simple_skins_id = skin_id
skin.simple_skins_id = mcl_skins.simple_skins[index].texture
mcl_skins.update_player_skin(player)
mcl_skins.show_formspec(player, active_tab, page_num)
end
@ -532,16 +558,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] then
for i, texture in pairs(mcl_skins[active_tab]) do
if texture == field then
skin[active_tab] = 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
end
end
end
-- See if field is a color
local number = tonumber(field)
@ -559,15 +584,6 @@ 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")
@ -579,17 +595,27 @@ local function init()
for _, item in pairs(json) do
mcl_skins.register_item(item)
end
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.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.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
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
})
end
init()

View File

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

View File

@ -21,6 +21,9 @@ 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
@ -66,13 +69,6 @@ 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,7 +14,9 @@ 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,
@ -36,7 +38,8 @@ 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
@ -45,10 +48,10 @@ function mcl_skins.get_skin_list()
end
function mcl_skins.get_node_id_by_player(player)
local skin = mcl_skins.players[player]
local skin = mcl_skins.player_skins[player]
local simple_skin = skin.simple_skins_id
if simple_skin then
skin = mcl_skins.simple_skins[skin.simple_skins_id]
skin = mcl_skins.texture_to_simple_skin[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

@ -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,5 @@
local function init_simple_skins()
local id, f, data, skin = 0
local id, f, data, skin = 2
local mod_path = minetest.get_modpath("mcl_skins")
while true do
@ -35,18 +35,13 @@ local function init_simple_skins()
end
-- add metadata to list
mcl_skins.simple_skins[id] = {
mcl_skins.register_simple_skin({
index = 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

@ -0,0 +1,3 @@
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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 B

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 680 B

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 B

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 B

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 B

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 B

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 B

After

Width:  |  Height:  |  Size: 151 B