Merge pull request '[heads] refactor, delete unnecessary textures and implement 16 direction head nodes' (#2550) from heads_16_direction into master

Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/2550
Reviewed-by: cora <cora@noreply.git.minetest.land>
This commit is contained in:
cora 2022-08-11 12:25:34 +00:00
commit db2f2cfc69
10 changed files with 396 additions and 141 deletions

View file

@ -1,5 +1,6 @@
local S = minetest.get_translator(minetest.get_current_modname()) local S = minetest.get_translator(minetest.get_current_modname())
local minetest = minetest
local mod_doc = minetest.get_modpath("doc") local mod_doc = minetest.get_modpath("doc")
local mod_screwdriver = minetest.get_modpath("screwdriver") local mod_screwdriver = minetest.get_modpath("screwdriver")
@ -8,159 +9,287 @@ if minetest.get_modpath("mcl_armor") then
equip_armor = mcl_armor.equip_on_use equip_armor = mcl_armor.equip_on_use
end end
-- Heads system mcl_heads = {}
local function addhead(name, texture, desc, longdesc, rangemob, rangefactor) -- rotations of head nodes within a quadrant (0° ≤ θ ≤ 90°)
local on_rotate_floor, on_rotate_wall mcl_heads.FLOOR_DEGREES = { [0]='', '22_5', '45', '67_5', }
if mod_screwdriver then
on_rotate_floor = function(pos, node, user, mode, new_param2) -- box of head nodes
if mode == screwdriver.ROTATE_AXIS then mcl_heads.FLOOR_BOX = { -0.25, -0.5, -0.25, 0.25, 0.0, 0.25, }
node.name = node.name .. "_wall"
node.param2 = minetest.dir_to_wallmounted(minetest.facedir_to_dir(node.param2)) -- floor head node nodedef template ------------------------------------------------------------------------------------
minetest.set_node(pos, node)
return true --- node definition template for floor mod heads
end mcl_heads.deftemplate_floor = {
end drawtype = "nodebox",
on_rotate_wall = function(pos, node, user, mode, new_param2) node_box = {
if mode == screwdriver.ROTATE_AXIS then type = "fixed",
node.name = string.sub(node.name, 1, string.len(node.name)-5) fixed = mcl_heads.FLOOR_BOX,
node.param2 = minetest.dir_to_facedir(minetest.wallmounted_to_dir(node.param2)) },
minetest.set_node(pos, node) groups = {
return true handy = 1,
end armor = 1,
armor_head = 1,
non_combat_armor = 1,
non_combat_armor_head = 1,
head = 1,
deco_block = 1,
dig_by_piston = 1,
},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype = "light",
paramtype2 = "facedir",
stack_max = 64,
sunlight_propagates = true,
sounds = mcl_sounds.node_sound_defaults{
footstep = {name="default_hard_footstep", gain=0.3},
},
is_ground_content = false,
_mcl_armor_element = "head",
_mcl_blast_resistance = 1,
_mcl_hardness = 1,
on_secondary_use = equip_armor,
}
mcl_heads.deftemplate_floor_angled = {
drawtype = "mesh",
selection_box = {
type = "fixed",
fixed = mcl_heads.FLOOR_BOX,
},
collision_box = {
type = "fixed",
fixed = mcl_heads.FLOOR_BOX,
},
groups = {
handy = 1,
head = 1,
deco_block = 1,
dig_by_piston = 1,
not_in_creative_inventory = 1,
},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype = "light",
paramtype2 = "facedir",
stack_max = 64,
sunlight_propagates = true,
sounds = mcl_sounds.node_sound_defaults{
footstep = {name="default_hard_footstep", gain=0.3},
},
is_ground_content = false,
_doc_items_create_entry = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 1,
}
function mcl_heads.deftemplate_floor.on_rotate(pos, node, user, mode, new_param2)
if mode == screwdriver.ROTATE_AXIS then
node.name = node.name .. "_wall"
node.param2 = minetest.dir_to_wallmounted(minetest.facedir_to_dir(node.param2))
minetest.set_node(pos, node)
return true
end
end
function mcl_heads.deftemplate_floor.on_place(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
local under = pointed_thing.under
local node = minetest.get_node(under)
local def = minetest.registered_nodes[node.name]
if not def then return itemstack end
-- Allow pointed node's on_rightclick callback to override place.
if placer and not placer:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(under, node, placer, itemstack) or itemstack
end end
end end
minetest.register_node("mcl_heads:"..name, { local above = pointed_thing.above
description = desc, local dir = {x = under.x - above.x, y = under.y - above.y, z = under.z - above.z}
_doc_items_longdesc = longdesc, local wdir = minetest.dir_to_wallmounted(dir)
drawtype = "nodebox",
is_ground_content = false, local itemstring = itemstack:get_name()
node_box = { local placestack = ItemStack(itemstack)
type = "fixed",
fixed = { -- place wall head node (elsewhere)
{ -0.25, -0.5, -0.25, 0.25, 0.0, 0.25, }, if wdir ~= 0 and wdir ~= 1 then
}, placestack:set_name(itemstring .."_wall")
}, itemstack = minetest.item_place(placestack, placer, pointed_thing, wdir)
groups = {handy = 1, armor = 1, armor_head = 1, non_combat_armor = 1, non_combat_armor_head = 1, head = 1, deco_block = 1, dig_by_piston = 1}, -- place floor head node (floor and ceiling)
else
local fdir = minetest.dir_to_facedir(dir)
-- determine the head node rotation based on player's yaw (in cw direction from North/Z+)
local yaw = math.pi*2 - placer:get_look_horizontal()
local rotation_level = math.min(math.max(math.round((yaw / (math.pi*2)) * 16), 0), 15)
placestack:set_name(itemstring ..mcl_heads.FLOOR_DEGREES[rotation_level % 4])
-- determine the head node face direction based on rotation level
fdir = math.floor(rotation_level / 4)
itemstack = minetest.item_place(placestack, placer, pointed_thing, fdir)
end
-- restore item from angled and wall head nodes
itemstack:set_name(itemstring)
return itemstack
end
-- wall head node nodedef template -------------------------------------------------------------------------------------
--- node definition template for wall mod heads
mcl_heads.deftemplate_wall = {
drawtype = "nodebox",
node_box = {
type = "wallmounted",
wall_bottom = { -0.25, -0.5, -0.25, 0.25, 0.0, 0.25, },
wall_top = { -0.25, 0.0, -0.25, 0.25, 0.5, 0.25, },
wall_side = { -0.5, -0.25, -0.25, 0.0, 0.25, 0.25, },
},
groups = {
handy = 1,
head = 1,
deco_block = 1,
dig_by_piston = 1,
not_in_creative_inventory = 1,
},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype = "light",
paramtype2 = "wallmounted",
stack_max = 64,
sunlight_propagates = true,
sounds = mcl_sounds.node_sound_defaults{
footstep = {name="default_hard_footstep", gain=0.3},
},
is_ground_content = false,
_doc_items_create_entry = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 1,
}
function mcl_heads.deftemplate_wall.on_rotate(pos, node, user, mode, new_param2)
if mode == screwdriver.ROTATE_AXIS then
node.name = string.sub(node.name, 1, string.len(node.name)-5)
node.param2 = minetest.dir_to_facedir(minetest.wallmounted_to_dir(node.param2))
minetest.set_node(pos, node)
return true
end
end
-- API functions -------------------------------------------------------------------------------------------------------
--- @class HeadDef
--- @field name string identifier for node
--- @field texture string armor texture for node
--- @field description string translated description
--- @field longdesc string translated doc description
--- @field range_mob string name of mob affected by range reduction
--- @field range_factor number factor of range reduction
--- registers a head
--- @param head_def HeadDef head node definition
function mcl_heads.register_head(head_def)
local name = "mcl_heads:" ..head_def.name
-- register the floor head node
minetest.register_node(name, table.update(table.copy(mcl_heads.deftemplate_floor), {
description = head_def.description,
_doc_items_longdesc = head_def.longdesc,
-- The head textures are based off the textures of an actual mob. -- The head textures are based off the textures of an actual mob.
tiles = { tiles = {
-- Note: bottom texture is overlaid over top texture to get rid of possible transparency. -- Note: bottom texture is overlaid over top texture to get rid of possible transparency.
-- This is required for skeleton skull and wither skeleton skull. -- This is required for skeleton skull and wither skeleton skull.
"[combine:16x16:-4,4="..texture, -- top -- Note: -x coords go right per-pixel, -y coords go down per-pixel
"([combine:16x16:-4,4="..texture..")^([combine:16x16:-12,4="..texture..")", -- bottom "[combine:16x16:-36,4=" ..head_def.texture, -- top
"[combine:16x16:-12,0="..texture, -- left "([combine:16x16:-36,4=" ..head_def.texture..")^([combine:16x16:-44,4="..head_def.texture..")", -- bottom
"[combine:16x16:4,0="..texture, -- right "[combine:16x16:-28,0=" ..head_def.texture, -- left
"[combine:16x16:-20,0="..texture, -- back "[combine:16x16:-44,0=" ..head_def.texture, -- right
"[combine:16x16:-4,0="..texture, -- front "[combine:16x16:-52,0=" ..head_def.texture, -- back
"[combine:16x16:-36,0=" ..head_def.texture, -- front
}, },
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype = "light",
stack_max = 64,
paramtype2 = "facedir",
sunlight_propagates = true,
walkable = true,
selection_box = {
type = "fixed",
fixed = { -0.25, -0.5, -0.25, 0.25, 0.0, 0.25, },
},
sounds = mcl_sounds.node_sound_defaults({
footstep = {name="default_hard_footstep", gain=0.3}
}),
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
-- no interaction possible with entities, for now.
return itemstack
end
local under = pointed_thing.under _mcl_armor_mob_range_mob = head_def.range_mob,
local node = minetest.get_node(under) _mcl_armor_mob_range_factor = head_def.range_factor,
local def = minetest.registered_nodes[node.name] _mcl_armor_texture = head_def.texture
if not def then return itemstack end }))
-- Call on_rightclick if the pointed node defines it -- register the angled floor head nodes
if placer and not placer:get_player_control().sneak then for i, d in ipairs(mcl_heads.FLOOR_DEGREES) do
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then minetest.register_node(name ..d, table.update(table.copy(mcl_heads.deftemplate_floor_angled), {
return minetest.registered_nodes[node.name].on_rightclick(under, node, placer, itemstack) or itemstack mesh = "mcl_heads_floor" ..d ..".obj",
end tiles = { head_def.texture },
end drop = name,
}))
local above = pointed_thing.above
local diff = {x = under.x - above.x, y = under.y - above.y, z = under.z - above.z}
local wdir = minetest.dir_to_wallmounted(diff)
local itemstring = itemstack:get_name()
local fakestack = ItemStack(itemstack)
--local idef = fakestack:get_definition()
local retval
if wdir == 0 or wdir == 1 then
return minetest.item_place(itemstack, placer, pointed_thing)
else
retval = fakestack:set_name("mcl_heads:"..name.."_wall")
end
if not retval then
return itemstack
end
itemstack = minetest.item_place(fakestack, placer, pointed_thing, wdir)
itemstack:set_name(itemstring)
return itemstack
end,
on_secondary_use = equip_armor,
on_rotate = on_rotate_floor,
_mcl_armor_mob_range_mob = rangemob,
_mcl_armor_mob_range_factor = rangefactor,
_mcl_armor_element = "head",
_mcl_armor_texture = "mcl_heads_" .. name .. ".png",
_mcl_blast_resistance = 1,
_mcl_hardness = 1,
})
minetest.register_node("mcl_heads:"..name.."_wall", {
_doc_items_create_entry = false,
drawtype = "nodebox",
is_ground_content = false,
node_box = {
type = "wallmounted",
wall_bottom = { -0.25, -0.5, -0.25, 0.25, 0.0, 0.25, },
wall_top = { -0.25, 0.0, -0.25, 0.25, 0.5, 0.25, },
wall_side = { -0.5, -0.25, -0.25, 0.0, 0.25, 0.25, },
},
groups = {handy=1, head=1, deco_block=1, dig_by_piston=1, not_in_creative_inventory=1},
-- The head textures are based off the textures of an actual mob.
tiles = {
{ name = "[combine:16x16:-4,-4="..texture, align_style = "world" }, -- front
{ name = "[combine:16x16:-20,-4="..texture, align_style = "world" }, -- back
{ name = "[combine:16x16:-8,-4="..texture, align_style = "world" }, -- left
{ name = "[combine:16x16:0,-4="..texture, align_style = "world" }, -- right
{ name = "([combine:16x16:-4,0="..texture..")^[transformR180", align_style = "node" }, -- top
{ name = "([combine:16x16:-4,8="..texture..")^([combine:16x16:-12,8="..texture..")", align_style = "node" }, -- bottom
},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype = "light",
stack_max = 64,
paramtype2 = "wallmounted",
sunlight_propagates = true,
walkable = true,
sounds = mcl_sounds.node_sound_defaults({
footstep = {name="default_hard_footstep", gain=0.3}
}),
drop = "mcl_heads:"..name,
on_rotate = on_rotate_wall,
_mcl_blast_resistance = 1,
_mcl_hardness = 1,
})
if mod_doc then
doc.add_entry_alias("nodes", "mcl_heads:" .. name, "nodes", "mcl_heads:" .. name .. "_wall")
end end
-- register the wall head node
minetest.register_node(name .."_wall", table.update(table.copy(mcl_heads.deftemplate_wall), {
-- The head textures are based off the textures of an actual mob.
-- Note: -x coords go right per-pixel, -y coords go down per-pixel
tiles = {
{ name = "[combine:16x16:-36,-4=" ..head_def.texture, align_style = "world" }, -- front
{ name = "[combine:16x16:-52,-4="..head_def.texture, align_style = "world" }, -- back
{ name = "[combine:16x16:-40,-4=" ..head_def.texture, align_style = "world" }, -- right
{ name = "[combine:16x16:-32,-4=" ..head_def.texture, align_style = "world" }, -- left
{ name = "([combine:16x16:-36,0=" ..head_def.texture ..")^[transformR180", align_style = "node" }, -- top
-- Note: bottom texture is overlaid over top texture to get rid of possible transparency.
-- This is required for skeleton skull and wither skeleton skull.
{ name = "([combine:16x16:-36,0=" ..head_def.texture ..")^([combine:16x16:-44,8=" ..head_def.texture..")", align_style = "node" }, -- bottom
},
drop = name,
}))
end end
-- Add heads -- initial heads -------------------------------------------------------------------------------------------------------
addhead("zombie", "mcl_heads_zombie_node.png", S("Zombie Head"), S("A zombie head is a small decorative block which resembles the head of a zombie. It can also be worn as a helmet, which reduces the detection range of zombies by 50%."), "mobs_mc:zombie", 0.5)
addhead("creeper", "mcl_heads_creeper_node.png", S("Creeper Head"), S("A creeper head is a small decorative block which resembles the head of a creeper. It can also be worn as a helmet, which reduces the detection range of creepers by 50%."), "mobs_mc:creeper", 0.5) mcl_heads.register_head{
name = "zombie",
texture = "mcl_heads_zombie.png",
description = S("Zombie Head"),
longdesc = S("A zombie head is a small decorative block which resembles the head of a zombie. It can also be worn as a helmet, which reduces the detection range of zombies by 50%."),
range_mob = "mobs_mc:zombie",
range_factor = 0.5,
}
mcl_heads.register_head{
name = "creeper",
texture = "mcl_heads_creeper.png",
description = S("Creeper Head"),
longdesc = S("A creeper head is a small decorative block which resembles the head of a creeper. It can also be worn as a helmet, which reduces the detection range of creepers by 50%."),
range_mob = "mobs_mc:creeper",
range_factor = 0.5,
}
-- Original Minecraft name: “Head” -- Original Minecraft name: “Head”
addhead("steve", "mcl_heads_steve_node.png", S("Human Head"), S("A human head is a small decorative block which resembles the head of a human (i.e. a player character). It can also be worn as a helmet for fun, but does not offer any protection.")) mcl_heads.register_head{
addhead("skeleton", "mcl_heads_skeleton_node.png", S("Skeleton Skull"), S("A skeleton skull is a small decorative block which resembles the skull of a skeleton. It can also be worn as a helmet, which reduces the detection range of skeletons by 50%."), "mobs_mc:skeleton", 0.5) name = "steve",
addhead("wither_skeleton", "mcl_heads_wither_skeleton_node.png", S("Wither Skeleton Skull"), S("A wither skeleton skull is a small decorative block which resembles the skull of a wither skeleton. It can also be worn as a helmet for fun, but does not offer any protection.")) texture = "mcl_heads_steve.png",
description = S("Human Head"),
longdesc = S("A human head is a small decorative block which resembles the head of a human (i.e. a player character). It can also be worn as a helmet for fun, but does not offer any protection."),
}
mcl_heads.register_head{
name = "skeleton",
texture = "mcl_heads_skeleton.png",
description = S("Skeleton Skull"),
longdesc = S("A skeleton skull is a small decorative block which resembles the skull of a skeleton. It can also be worn as a helmet, which reduces the detection range of skeletons by 50%."),
range_mob = "mobs_mc:skeleton",
range_factor = 0.5,
}
mcl_heads.register_head{
name = "wither_skeleton",
texture = "mcl_heads_wither_skeleton.png",
description = S("Wither Skeleton Skull"),
longdesc = S("A wither skeleton skull is a small decorative block which resembles the skull of a wither skeleton. It can also be worn as a helmet for fun, but does not offer any protection."),
}

View file

@ -0,0 +1,42 @@
# Blender v2.93.9 OBJ File: 'mcl_heads_floor_0.blend'
# www.blender.org
mtllib mcl_heads_floor22_5.mtl
o Cube.001
v -0.326641 -0.500000 0.135299
v -0.326641 0.000000 0.135299
v -0.135299 -0.500000 -0.326641
v -0.135299 0.000000 -0.326641
v 0.135299 -0.500000 0.326641
v 0.135299 0.000000 0.326641
v 0.326641 -0.500000 -0.135299
v 0.326641 0.000000 -0.135299
vt 0.875000 0.500000
vt 0.875000 0.750000
vt 0.750000 0.750000
vt 0.750000 0.500000
vt 0.625000 0.750000
vt 0.625000 0.500000
vt 0.500000 0.750000
vt 0.500000 0.500000
vt 1.000000 0.500000
vt 1.000000 0.750000
vt 0.875000 0.750000
vt 0.875000 1.000000
vt 0.750000 1.000000
vt 0.750000 0.750000
vt 0.750000 1.000000
vt 0.625000 1.000000
vn -0.9239 0.0000 -0.3827
vn 0.3827 0.0000 -0.9239
vn 0.9239 0.0000 0.3827
vn -0.3827 0.0000 0.9239
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Material.001
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/4/2 4/3/2 8/5/2 7/6/2
f 7/6/3 8/5/3 6/7/3 5/8/3
f 5/9/4 6/10/4 2/2/4 1/1/4
f 3/11/5 7/12/5 5/13/5 1/14/5
f 8/5/6 4/3/6 2/15/6 6/16/6

View file

@ -0,0 +1,42 @@
# Blender v2.93.9 OBJ File: 'mcl_heads_floor_0.blend'
# www.blender.org
mtllib mcl_heads_floor45.mtl
o Cube.002
v -0.353553 -0.500000 0.000000
v -0.353553 0.000000 0.000000
v 0.000000 -0.500000 -0.353553
v 0.000000 0.000000 -0.353553
v 0.000000 -0.500000 0.353553
v 0.000000 0.000000 0.353553
v 0.353553 -0.500000 0.000000
v 0.353553 0.000000 0.000000
vt 0.875000 0.500000
vt 0.875000 0.750000
vt 0.750000 0.750000
vt 0.750000 0.500000
vt 0.625000 0.750000
vt 0.625000 0.500000
vt 0.500000 0.750000
vt 0.500000 0.500000
vt 1.000000 0.500000
vt 1.000000 0.750000
vt 0.875000 0.750000
vt 0.875000 1.000000
vt 0.750000 1.000000
vt 0.750000 0.750000
vt 0.750000 1.000000
vt 0.625000 1.000000
vn -0.7071 0.0000 -0.7071
vn 0.7071 0.0000 -0.7071
vn 0.7071 0.0000 0.7071
vn -0.7071 0.0000 0.7071
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Material.002
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/4/2 4/3/2 8/5/2 7/6/2
f 7/6/3 8/5/3 6/7/3 5/8/3
f 5/9/4 6/10/4 2/2/4 1/1/4
f 3/11/5 7/12/5 5/13/5 1/14/5
f 8/5/6 4/3/6 2/15/6 6/16/6

View file

@ -0,0 +1,42 @@
# Blender v2.93.9 OBJ File: 'mcl_heads_floor_0.blend'
# www.blender.org
mtllib mcl_heads_floor67_5.mtl
o Cube.003
v -0.326641 -0.500000 -0.135299
v -0.326641 0.000000 -0.135299
v 0.135299 -0.500000 -0.326641
v 0.135299 0.000000 -0.326641
v -0.135299 -0.500000 0.326641
v -0.135299 0.000000 0.326641
v 0.326641 -0.500000 0.135299
v 0.326641 0.000000 0.135299
vt 0.875000 0.500000
vt 0.875000 0.750000
vt 0.750000 0.750000
vt 0.750000 0.500000
vt 0.625000 0.750000
vt 0.625000 0.500000
vt 0.500000 0.750000
vt 0.500000 0.500000
vt 1.000000 0.500000
vt 1.000000 0.750000
vt 0.875000 0.750000
vt 0.875000 1.000000
vt 0.750000 1.000000
vt 0.750000 0.750000
vt 0.750000 1.000000
vt 0.625000 1.000000
vn -0.3827 0.0000 -0.9239
vn 0.9239 0.0000 -0.3827
vn 0.3827 0.0000 0.9239
vn -0.9239 0.0000 0.3827
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Material.003
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/4/2 4/3/2 8/5/2 7/6/2
f 7/6/3 8/5/3 6/7/3 5/8/3
f 5/9/4 6/10/4 2/2/4 1/1/4
f 3/11/5 7/12/5 5/13/5 1/14/5
f 8/5/6 4/3/6 2/15/6 6/16/6

Binary file not shown.

Before

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 970 B

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB