Compare commits

..

6 Commits

76 changed files with 681 additions and 338 deletions

View File

@ -437,9 +437,9 @@ cboat.selectionbox = {-0.7, -0.15, -0.7, 0.7, 0.75, 0.7}
minetest.register_entity("mcl_boats:chest_boat", cboat)
mcl_entity_invs.register_inv("mcl_boats:chest_boat","Boat",27)
local boat_ids = { "boat", "boat_spruce", "boat_birch", "boat_jungle", "boat_acacia", "boat_dark_oak", "boat_obsidian", "boat_mangrove", "chest_boat", "chest_boat_spruce", "chest_boat_birch", "chest_boat_jungle", "chest_boat_acacia", "chest_boat_dark_oak", "chest_boat_mangrove" }
local names = { S("Oak Boat"), S("Spruce Boat"), S("Birch Boat"), S("Jungle Boat"), S("Acacia Boat"), S("Dark Oak Boat"), S("Obsidian Boat"), S("Mangrove Boat"), S("Oak Chest Boat"), S("Spruce Chest Boat"), S("Birch Chest Boat"), S("Jungle Chest Boat"), S("Acacia Chest Boat"), S("Dark Oak Chest Boat"), S("Mangrove Chest Boat") }
local craftstuffs = { "mcl_core:wood", "mcl_core:sprucewood", "mcl_core:birchwood", "mcl_core:junglewood", "mcl_core:acaciawood", "mcl_core:darkwood", "mcl_core:obsidian", "mcl_mangrove:mangrove_wood" }
local boat_ids = { "boat", "boat_spruce", "boat_birch", "boat_jungle", "boat_acacia", "boat_dark_oak", "boat_obsidian", "boat_mangrove", "boat_cherry", "chest_boat", "chest_boat_spruce", "chest_boat_birch", "chest_boat_jungle", "chest_boat_acacia", "chest_boat_dark_oak", "chest_boat_mangrove", "chest_boat_cherry" }
local names = { S("Oak Boat"), S("Spruce Boat"), S("Birch Boat"), S("Jungle Boat"), S("Acacia Boat"), S("Dark Oak Boat"), S("Obsidian Boat"), S("Mangrove Boat"), S("Cherry Boat"), S("Oak Chest Boat"), S("Spruce Chest Boat"), S("Birch Chest Boat"), S("Jungle Chest Boat"), S("Acacia Chest Boat"), S("Dark Oak Chest Boat"), S("Mangrove Chest Boat"), S("Cherry Chest Boat") }
local craftstuffs = { "mcl_core:wood", "mcl_core:sprucewood", "mcl_core:birchwood", "mcl_core:junglewood", "mcl_core:acaciawood", "mcl_core:darkwood", "mcl_core:obsidian", "mcl_mangrove:mangrove_wood", "mcl_cherry_blossom:cherrywood" }
for b=1, #boat_ids do
local itemstring = "mcl_boats:"..boat_ids[b]

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

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

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

@ -0,0 +1,86 @@
-- Crafting
local planks = "mcl_cherry_blossom:cherrywood"
local logs = "mcl_cherry_blossom:cherrytree"
local stripped_logs = "mcl_cherry_blossom:stripped_cherrytree"
minetest.register_craft({
output = "mcl_cherry_blossom:cherrytree_bark 3",
recipe = {
{ logs, logs },
{ logs, logs },
}
})
minetest.register_craft({
output = "mcl_cherry_blossom:stripped_cherrytree_bark 3",
recipe = {
{ stripped_logs, stripped_logs },
{ stripped_logs, stripped_logs },
}
})
minetest.register_craft({
output = "mcl_cherry_blossom:cherrywood 4",
recipe = {
{ logs },
}
})
minetest.register_craft({
output = "mcl_chery_blossom:cherrydoor 3",
recipe = {
{planks, planks},
{planks, planks},
{planks, planks}
}
})
minetest.register_craft({
output = "mcl_cherry_blossom:cherrytrapdoor 2",
recipe = {
{planks, planks, planks},
{planks, planks, planks},
}
})
minetest.register_craft({
output = "mcl_fences:cherry_fence 3",
recipe = {
{planks, "mcl_core:stick", planks},
{planks, "mcl_core:stick", planks},
}
})
minetest.register_craft({
output = "mcl_fences:cherry_fence_gate",
recipe = {
{"mcl_core:stick", planks, "mcl_core:stick"},
{"mcl_core:stick", planks, "mcl_core:stick"},
}
})
mcl_signs.register_sign_craft("mcl_cherry_blossom", "mcl_cherry_blossom:cherrywood", "cherrywood")
-- Smelting
minetest.register_craft({
type = "fuel",
recipe = "mcl_cherry_blossom:cherrydoor",
burntime = 10,
})
minetest.register_craft({
type = "fuel",
recipe = "mcl_cherry_blossom:cherrytrapdoor",
burntime = 15,
})
minetest.register_craft({
type = "fuel",
recipe = "mcl_cherry_blossom:pressure_plate_cherrywood_off",
burntime = 15
})
minetest.register_craft({
type = "fuel",
recipe = "mesecons_button:button_cherrywood_off",
burntime = 5,
})

View File

@ -0,0 +1,56 @@
-- Tree Growth
-- TODO: Use better spawning behavior and wood api when wood api is finished.
function mcl_cherry_blossom.generate_cherry_tree(pos)
local pr = PseudoRandom(pos.x+pos.y+pos.z)
local r = pr:next(1,3)
local modpath = minetest.get_modpath("mcl_cherry_blossom")
local path = modpath.."/schematics/mcl_cherry_blossom_tree_"..tostring(r)..".mts"
if mcl_core.check_growth_width(pos,7,8) then
minetest.set_node(pos, {name = "air"})
if r == 1 then
minetest.place_schematic({x = pos.x-2, y = pos.y, z = pos.z-2}, path, "random", nil, false)
elseif r == 2 then
minetest.place_schematic({x = pos.x-2, y = pos.y, z = pos.z-2}, path, nil, nil, false)
elseif r == 3 then
minetest.place_schematic({x = pos.x-3, y = pos.y, z = pos.z-3}, path, nil, nil, false)
end
end
end
minetest.register_abm({
label = "Cherry Tree Growth",
nodenames = "mcl_cherry_blossom:cherrysapling",
interval = 30,
chance = 5,
action = function(pos,node)
mcl_cherry_blossom.generate_cherry_tree(pos)
end,
})
local cherry_particle = {
velocity = vector.new(0,0,0),
size = math.random(1.3,2.5),
texture = "mcl_cherry_blossom_particle.png",
collision_removal = false,
}
minetest.register_abm({
label = "Cherry Blossom Particles",
nodenames = {"mcl_cherry_blossom:cherryleaves"},
interval = 5,
chance = 10,
action = function(pos, node)
minetest.after(math.random(0.1,1.5),function()
local pt = table.copy(cherry_particle)
pt.acceleration = vector.new(0,0,0)
pt.collisiondetection = false
pt.pos = vector.offset(pos,math.random(-0.5,0.5),-0.51,math.random(-0.5,0.5))
minetest.add_particle(pt)
pt.acceleration = vector.new(0,-1,0)
pt.collisiondetection = true
pt.expirationtime = math.random(1.2,4.5)
minetest.add_particle(pt)
end)
end
})

View File

@ -0,0 +1,6 @@
mcl_cherry_blossom = {}
local modpath = minetest.get_modpath("mcl_cherry_blossom")
dofile(modpath.."/nodes.lua") -- Load Nodes
dofile(modpath.."/crafting.lua") -- Load Crafting Recipes
dofile(modpath.."/growth.lua") -- Load Cherry Blossom Tree Growth

View File

@ -0,0 +1,3 @@
title = mcl_cherry_blossom
author = PrairieWind
depends = mcl_sounds, mcl_util, mcl_core, mcl_doors, mcl_stairs, mcl_signs, mcl_fences, mesecons_pressureplates, mesecons_button, mcl_boats

View File

@ -0,0 +1,264 @@
local S = minetest.get_translator(minetest.get_current_modname())
-- Logs
minetest.register_node("mcl_cherry_blossom:cherrytree", {
description = S("Cherry Log"),
_doc_items_longdesc = S("The trunk of an cherry blossom tree."),
_doc_items_hidden = false,
tiles = {"mcl_cherry_blossom_log_top.png", "mcl_cherry_blossom_log_top.png", "mcl_cherry_blossom_log.png"},
paramtype2 = "facedir",
on_place = mcl_util.rotate_axis,
after_destruct = mcl_core.update_leaves,
stack_max = 64,
groups = {handy=1,axey=1, tree=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
sounds = mcl_sounds.node_sound_wood_defaults(),
on_rotate = on_rotate,
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
_mcl_stripped_variant = "mcl_cherry_blossom:stripped_cherrytree",
})
minetest.register_node("mcl_cherry_blossom:stripped_cherrytree", {
description = S("Stripped Cherry Log"),
_doc_items_longdesc = S("The stripped trunk of an cherry blossom tree."),
_doc_items_hidden = false,
tiles = {"mcl_cherry_blossom_log_top_stripped.png", "mcl_cherry_blossom_log_top_stripped.png", "mcl_cherry_blossom_log_stripped.png"},
paramtype2 = "facedir",
on_place = mcl_util.rotate_axis,
stack_max = 64,
groups = {handy=1, axey=1, tree=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
sounds = mcl_sounds.node_sound_wood_defaults(),
on_rotate = on_rotate,
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
})
-- Bark
minetest.register_node("mcl_cherry_blossom:cherrytree_bark", {
description = S("Cherry Bark"),
_doc_items_longdesc = S("This is a decorative block surrounded by the bark of a tree trunk."),
tiles = {"mcl_cherry_blossom_log.png"},
paramtype2 = "facedir",
on_place = mcl_util.rotate_axis,
stack_max = 64,
groups = {handy=1,axey=1, bark=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
sounds = mcl_sounds.node_sound_wood_defaults(),
is_ground_content = false,
on_rotate = on_rotate,
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
_mcl_stripped_variant = "mcl_cherry_blossom:stripped_cherrytree_bark",
})
minetest.register_node("mcl_cherry_blossom:stripped_cherrytree_bark", {
description = S("Stripped Cherry Wood"),
_doc_items_longdesc = S("The stripped wood of an cherry blossom tree."),
tiles = {"mcl_cherry_blossom_log_stripped.png"},
paramtype2 = "facedir",
on_place = mcl_util.rotate_axis,
stack_max = 64,
groups = {handy=1, axey=1, bark=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
sounds = mcl_sounds.node_sound_wood_defaults(),
is_ground_content = false,
on_rotate = on_rotate,
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
})
--Planks
minetest.register_node("mcl_cherry_blossom:cherrywood", {
description = S("Cherry Wood Planks"),
_doc_items_longdesc = doc.sub.items.temp.build,
_doc_items_hidden = false,
tiles = {"mcl_cherry_blossom_planks.png"},
stack_max = 64,
is_ground_content = false,
groups = {handy=1,axey=1, flammable=3,wood=1,building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=20},
sounds = mcl_sounds.node_sound_wood_defaults(),
_mcl_blast_resistance = 3,
_mcl_hardness = 2,
})
-- Leaves
local stick_chances = {50, 45, 30, 35, 10}
local sapling_chances = {20, 16, 12, 10}
local function get_drops(fortune_level)
local drop = {
max_items = 1,
items = {
{
items = {"mcl_cherry_blossom:cherrysapling"},
rarity = sapling_chances[fortune_level + 1] or sapling_chances[fortune_level]
},
{
items = {"mcl_core:stick 1"},
rarity = stick_chances[fortune_level + 1]
},
{
items = {"mcl_core:stick 2"},
rarity = stick_chances[fortune_level + 1]
},
}
}
return drop
end
local l_def = {
description = S("Cherry Leaves"),
_doc_items_longdesc = S("Cherry blossom leaves are grown from cherry blossom trees."),
_doc_items_hidden = false,
drawtype = "allfaces_optional",
waving = 2,
tiles = {"mcl_cherry_blossom_leaves.png"},
color = color,
paramtype = "light",
stack_max = 64,
groups = {
handy = 1, hoey = 1, shearsy = 1, swordy = 1, dig_by_piston = 1,
flammable = 2, fire_encouragement = 30, fire_flammability = 60,
leaves = 1, deco_block = 1, compostability = 30
},
drop = get_drops(0),
_mcl_shears_drop = true,
sounds = mcl_sounds.node_sound_leaves_defaults(),
_mcl_blast_resistance = 0.2,
_mcl_hardness = 0.2,
_mcl_silk_touch_drop = true,
_mcl_fortune_drop = { get_drops(1), get_drops(2), get_drops(3), get_drops(4) },
after_place_node = function(pos)
mcl_core.make_player_leaves(pos) -- Leaves placed by the player should always be player leaves.
end,
}
minetest.register_node("mcl_cherry_blossom:cherryleaves", l_def)
local o_def = table.copy(l_def)
o_def._doc_items_create_entry = false
o_def.groups.not_in_creative_inventory = 1
o_def.groups.orphan_leaves = 1
o_def._mcl_shears_drop = {"mcl_cherry_blossom:cherryleaves"}
o_def._mcl_silk_touch_drop = {"mcl_cherry_blossom:cherryleaves"}
minetest.register_node("mcl_cherry_blossom:cherryleaves" .. "_orphan", o_def)
-- Sapling
minetest.register_node("mcl_cherry_blossom:cherrysapling", {
description = S("Cherry Sapling"),
_tt_help = tt_help,
_doc_items_longdesc = S("Cherry blossom sapling can be planted to grow cherry trees"),
_doc_items_hidden = false,
drawtype = "plantlike",
waving = 1,
visual_scale = 1.0,
tiles = {"mcl_cherry_blossom_sapling.png"},
inventory_image = "mcl_cherry_blossom_sapling.png",
wield_image = "mcl_cherry_blossom_sapling.png",
paramtype = "light",
sunlight_propagates = true,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-4/16, -0.5, -4/16, 4/16, 0.25, 4/16}
},
stack_max = 64,
groups = {
plant = 1, sapling = 1, attached_node = 1,
deco_block = 1, dig_immediate = 3, dig_by_water = 1, dig_by_piston = 1,
destroy_by_lava_flow = 1, compostability = 30
},
sounds = mcl_sounds.node_sound_leaves_defaults(),
on_construct = function(pos)
--local meta = minetest.get_meta(pos)
--meta:set_int("stage", 0)
-- TODO Uncomment above when wood api is implemented with the current mcl_core tree growth code.
end,
on_place = mcl_util.generate_on_place_plant_function(function(pos, node)
local node_below = minetest.get_node_or_nil({x=pos.x,y=pos.y-1,z=pos.z})
if not node_below then return false end
local nn = node_below.name
return minetest.get_item_group(nn, "grass_block") == 1 or
nn == "mcl_core:podzol" or nn == "mcl_core:podzol_snow" or
nn == "mcl_core:dirt" or nn == "mcl_core:mycelium" or nn == "mcl_core:coarse_dirt"
end),
node_placement_prediction = "",
_mcl_blast_resistance = 0,
_mcl_hardness = 0,
})
-- Door and Trapdoor
mcl_doors:register_door("mcl_cherry_blossom:cherrydoor", {
description = S("Cherry Door"),
_doc_items_longdesc = S("Wooden doors are 2-block high barriers which can be opened or closed by hand and by a redstone signal."),
_doc_items_usagehelp = S("To open or close a wooden door, rightclick it or supply its lower half with a redstone signal."),
inventory_image = "mcl_cherry_blossom_door_inv.png",
groups = {handy=1,axey=1, material_wood=1, flammable=-1},
_mcl_hardness = 3,
_mcl_blast_resistance = 3,
tiles_bottom = {"mcl_cherry_blossom_door_bottom.png", "mcl_cherry_blossom_door_side_bottom.png"},
tiles_top = {"mcl_cherry_blossom_door_top.png", "mcl_cherry_blossom_door_side_top.png"},
sounds = mcl_sounds.node_sound_wood_defaults(),
})
mcl_doors:register_trapdoor("mcl_cherry_blossom:cherrytrapdoor", {
description = S("Cherry Trapdoor"),
_doc_items_longdesc = S("Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder."),
_doc_items_usagehelp = S("To open or close the trapdoor, rightclick it or send a redstone signal to it."),
tile_front = "mcl_cherry_blossom_trapdoor.png",
tile_side = "mcl_cherry_blossom_trapdoor_side.png",
wield_image = "mcl_cherry_blossom_trapdoor.png",
groups = {handy=1,axey=1, mesecon_effector_on=1, material_wood=1, flammable=-1},
_mcl_hardness = 3,
_mcl_blast_resistance = 3,
sounds = mcl_sounds.node_sound_wood_defaults(),
})
-- Stairs and Slabs
mcl_stairs.register_stair("cherrywood", "mcl_cherry_blossom:cherrywood",
{handy=1,axey=1, flammable=3,wood_stairs=1, material_wood=1, fire_encouragement=5, fire_flammability=20},
{"mcl_cherry_blossom_planks.png"},
S("Cherry Stairs"),
mcl_sounds.node_sound_wood_defaults(), 3, 2,
"woodlike")
mcl_stairs.register_slab("cherrywood", "mcl_cherry_blossom:cherrywood",
{handy=1,axey=1, flammable=3,wood_slab=1, material_wood=1, fire_encouragement=5, fire_flammability=20},
{"mcl_cherry_blossom_planks.png"},
S("Cherry Slab"),
mcl_sounds.node_sound_wood_defaults(), 3, 2,
S("Double Cherry Slab"))
-- Signs
mcl_signs.register_sign_custom("mcl_cherry_blossom", "cherrywood",
"mcl_cherry_blossom_sign.png", nil,
"mcl_cherry_blossom_sign_inv.png", "mcl_cherry_blossom_sign_inv.png", "Cherry Sign")
-- Fences & Gates
mcl_fences.register_fence_and_fence_gate("cherry_fence", S("Cherry Fence"), S("Cherry Gate"),
"mcl_cherry_blossom_planks.png", {handy=1, axey=1, flammable=2, fence_wood=1, fire_encouragement=5, fire_flammability=20}, 2, 15,
{"group:fence_wood"}, mcl_sounds.node_sound_wood_defaults())
-- Redstone
mesecon.register_pressure_plate(
"mcl_cherry_blossom:pressure_plate_cherrywood",
S("Cherry Pressure Plate"),
{"mcl_cherry_blossom_planks.png"},
{"mcl_cherry_blossom_planks.png"},
"mcl_cherry_blossom_planks.png",
nil,
{{"mcl_cherry_blossom:cherrywood", "mcl_cherry_blossom:cherrywood"}},
mcl_sounds.node_sound_wood_defaults(),
{axey=1, material_wood=1},
nil,
S("A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it."))
mesecon.register_button(
"cherrywood",
S("Cherry Button"),
"mcl_cherry_blossom_planks.png",
"mcl_cherry_blossom:cherrywood",
mcl_sounds.node_sound_wood_defaults(),
{material_wood=1,handy=1,axey=1},
1.5,
true,
S("A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. Wooden buttons may also be pushed by arrows."),
"mesecons_button_push_wood")

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

@ -89,6 +89,7 @@ local loottable =
items = {
{ itemstring = "mcl_farming:wheat_item", weight = 20, amount_min = 1, amount_max = 4 },
{ itemstring = "mcl_farming:bread", weight = 20 },
{ itemstring = "mcl_cherry_blossom:cherrysapling", weight = 15, amount_min = 1, amount_max = 4 }, -- FIXME: Remove when cherry blossom map generation is implemented.
{ itemstring = "mcl_core:coal_lump", weight = 15, amount_min = 1, amount_max = 4 },
{ itemstring = "mesecons:redstone", weight = 15, amount_min = 1, amount_max = 4 },
{ itemstring = "mcl_farming:beetroot_seeds", weight = 10, amount_min = 2, amount_max = 4 },

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.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 770 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

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