Digging time groups WIP

This commit is contained in:
Perttu Ahola 2012-02-28 19:45:23 +02:00
parent f21291211c
commit 562ac3bce9
21 changed files with 695 additions and 704 deletions

@ -327,9 +327,8 @@ function minetest.node_dig(pos, node, digger)
local drops = minetest.get_node_drops(node.name, wielded:get_name()) local drops = minetest.get_node_drops(node.name, wielded:get_name())
-- Wear out tool -- Wear out tool
mp = def.material tp = wielded:get_tool_capabilities()
tp = wielded:get_tool_digging_properties() dp = minetest.get_dig_params(def.groups, tp)
dp = minetest.get_digging_properties(mp, tp)
wielded:add_wear(dp.wear) wielded:add_wear(dp.wear)
digger:set_wielded_item(wielded) digger:set_wielded_item(wielded)
@ -366,7 +365,7 @@ minetest.nodedef_default = {
stack_max = 99, stack_max = 99,
usable = false, usable = false,
liquids_pointable = false, liquids_pointable = false,
tool_digging_properties = nil, tool_capabilities = nil,
-- Interaction callbacks -- Interaction callbacks
on_place = minetest.item_place, on_place = minetest.item_place,
@ -425,7 +424,7 @@ minetest.craftitemdef_default = {
wield_scale = {x=1,y=1,z=1}, wield_scale = {x=1,y=1,z=1},
stack_max = 99, stack_max = 99,
liquids_pointable = false, liquids_pointable = false,
tool_digging_properties = nil, tool_capabilities = nil,
-- Interaction callbacks -- Interaction callbacks
on_place = minetest.item_place, on_place = minetest.item_place,
@ -443,7 +442,7 @@ minetest.tooldef_default = {
wield_scale = {x=1,y=1,z=1}, wield_scale = {x=1,y=1,z=1},
stack_max = 1, stack_max = 1,
liquids_pointable = false, liquids_pointable = false,
tool_digging_properties = nil, tool_capabilities = nil,
-- Interaction callbacks -- Interaction callbacks
on_place = minetest.item_place, on_place = minetest.item_place,
@ -461,7 +460,7 @@ minetest.noneitemdef_default = { -- This is used for the hand and unknown items
wield_scale = {x=1,y=1,z=1}, wield_scale = {x=1,y=1,z=1},
stack_max = 99, stack_max = 99,
liquids_pointable = false, liquids_pointable = false,
tool_digging_properties = nil, tool_capabilities = nil,
-- Interaction callbacks -- Interaction callbacks
on_place = nil, on_place = nil,
@ -643,7 +642,7 @@ function minetest.register_tool(name, tooldef)
if tooldef.inventory_image == nil and tooldef.image ~= nil then if tooldef.inventory_image == nil and tooldef.image ~= nil then
tooldef.inventory_image = tooldef.image tooldef.inventory_image = tooldef.image
end end
if tooldef.tool_digging_properties == nil and if tooldef.tool_capabilities == nil and
(tooldef.full_punch_interval ~= nil or (tooldef.full_punch_interval ~= nil or
tooldef.basetime ~= nil or tooldef.basetime ~= nil or
tooldef.dt_weight ~= nil or tooldef.dt_weight ~= nil or
@ -655,7 +654,7 @@ function minetest.register_tool(name, tooldef)
tooldef.dd_crackiness ~= nil or tooldef.dd_crackiness ~= nil or
tooldef.dd_crumbliness ~= nil or tooldef.dd_crumbliness ~= nil or
tooldef.dd_cuttability ~= nil) then tooldef.dd_cuttability ~= nil) then
tooldef.tool_digging_properties = { tooldef.tool_capabilities = {
full_punch_interval = tooldef.full_punch_interval, full_punch_interval = tooldef.full_punch_interval,
basetime = tooldef.basetime, basetime = tooldef.basetime,
dt_weight = tooldef.dt_weight, dt_weight = tooldef.dt_weight,
@ -711,18 +710,14 @@ minetest.register_item(":", {
type = "none", type = "none",
wield_image = "wieldhand.png", wield_image = "wieldhand.png",
wield_scale = {x=1,y=1,z=2.5}, wield_scale = {x=1,y=1,z=2.5},
tool_digging_properties = { tool_capabilities = {
full_punch_interval = 2.0, full_punch_interval = 2.0,
basetime = 0.5, max_drop_level = 0,
dt_weight = 1, groupcaps = {
dt_crackiness = 0, fleshy = {times={[2]=2.00, [3]=1.00}, maxwear=0, maxlevel=1},
dt_crumbliness = -1, crumbly = {times={[3]=0.70}, maxwear=0, maxlevel=1},
dt_cuttability = 0, snappy = {times={[3]=0.70}, maxwear=0, maxlevel=1},
basedurability = 50, }
dd_weight = 0,
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
} }
}) })

@ -263,7 +263,7 @@
-- - get_free_space(): returns get_stack_max() - get_count() -- - get_free_space(): returns get_stack_max() - get_count()
-- - is_known(): returns true if the item name refers to a defined item type -- - is_known(): returns true if the item name refers to a defined item type
-- - get_definition(): returns the item definition table -- - get_definition(): returns the item definition table
-- - get_tool_digging_properties(): returns the digging properties of the item, -- - get_tool_capabilities(): returns the digging properties of the item,
-- ^ or those of the hand if none are defined for this item type -- ^ or those of the hand if none are defined for this item type
-- - add_wear(amount): increases wear by amount if the item is a tool -- - add_wear(amount): increases wear by amount if the item is a tool
-- - add_item(item): put some item or stack onto this stack, -- - add_item(item): put some item or stack onto this stack,
@ -322,7 +322,7 @@
-- wield_scale = {x=1,y=1,z=1}, -- wield_scale = {x=1,y=1,z=1},
-- stack_max = 99, -- stack_max = 99,
-- liquids_pointable = false, -- liquids_pointable = false,
-- tool_digging_properties = { -- tool_capabilities = {
-- full_punch_interval = 1.0, -- full_punch_interval = 1.0,
-- basetime = 1.0, -- basetime = 1.0,
-- dt_weight = 0.5, -- dt_weight = 0.5,
@ -371,14 +371,6 @@
-- light_source = 0, -- light_source = 0,
-- damage_per_second = 0, -- damage_per_second = 0,
-- selection_box = {type="regular"}, -- selection_box = {type="regular"},
-- material = {
-- diggablity = "normal",
-- weight = 0,
-- crackiness = 0,
-- crumbliness = 0,
-- cuttability = 0,
-- flammability = 0,
-- },
-- legacy_facedir_simple = false, -- Support maps made in and before January 2012 -- legacy_facedir_simple = false, -- Support maps made in and before January 2012
-- legacy_wallmounted = false, -- Support maps made in and before January 2012 -- legacy_wallmounted = false, -- Support maps made in and before January 2012
-- } -- }
@ -455,209 +447,145 @@ default = {}
minetest.register_tool("default:pick_wood", { minetest.register_tool("default:pick_wood", {
description = "Wooden Pickaxe", description = "Wooden Pickaxe",
inventory_image = "default_tool_woodpick.png", inventory_image = "default_tool_woodpick.png",
tool_digging_properties = { tool_capabilities = {
basetime = 2.0, max_drop_level=0,
dt_weight = 0, groupcaps={
dt_crackiness = -0.5, cracky={times={[2]=1.50, [3]=0.80}, maxwear=0.1, maxlevel=1}
dt_crumbliness = 2, }
dt_cuttability = 0,
basedurability = 30,
dd_weight = 0,
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
}, },
}) })
minetest.register_tool("default:pick_stone", { minetest.register_tool("default:pick_stone", {
description = "Stone Pickaxe", description = "Stone Pickaxe",
inventory_image = "default_tool_stonepick.png", inventory_image = "default_tool_stonepick.png",
tool_digging_properties = { tool_capabilities = {
basetime = 1.5, max_drop_level=0,
dt_weight = 0, groupcaps={
dt_crackiness = -0.5, cracky={times={[1]=1.50, [2]=0.80, [3]=0.60}, maxwear=0.05, maxlevel=1}
dt_crumbliness = 2, }
dt_cuttability = 0,
basedurability = 100,
dd_weight = 0,
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
}, },
}) })
minetest.register_tool("default:pick_steel", { minetest.register_tool("default:pick_steel", {
description = "Steel Pickaxe", description = "Steel Pickaxe",
inventory_image = "default_tool_steelpick.png", inventory_image = "default_tool_steelpick.png",
tool_digging_properties = { tool_capabilities = {
basetime = 1.0, max_drop_level=1,
dt_weight = 0, groupcaps={
dt_crackiness = -0.5, cracky={times={[1]=1.00, [2]=0.60, [3]=0.40}, maxwear=0.1, maxlevel=2}
dt_crumbliness = 2, }
dt_cuttability = 0,
basedurability = 333,
dd_weight = 0,
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
}, },
}) })
minetest.register_tool("default:pick_mese", { minetest.register_tool("default:pick_mese", {
description = "Mese Pickaxe", description = "Mese Pickaxe",
inventory_image = "default_tool_mesepick.png", inventory_image = "default_tool_mesepick.png",
tool_digging_properties = { tool_capabilities = {
basetime = 0, max_drop_level=3,
dt_weight = 0, groupcaps={
dt_crackiness = 0, cracky={times={[1]=0.2, [2]=0.2, [3]=0.2}, maxwear=0.05, maxlevel=3},
dt_crumbliness = 0, crumbly={times={[1]=0.2, [2]=0.2, [3]=0.2}, maxwear=0.05, maxlevel=3},
dt_cuttability = 0, snappy={times={[1]=0.2, [2]=0.2, [3]=0.2}, maxwear=0.05, maxlevel=3}
basedurability = 1337, }
dd_weight = 0,
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
}, },
}) })
minetest.register_tool("default:shovel_wood", { minetest.register_tool("default:shovel_wood", {
description = "Wooden Shovel", description = "Wooden Shovel",
inventory_image = "default_tool_woodshovel.png", inventory_image = "default_tool_woodshovel.png",
tool_digging_properties = { tool_capabilities = {
basetime = 2.0, max_drop_level=0,
dt_weight = 0.5, groupcaps={
dt_crackiness = 2, crumbly={times={[1]=1.50, [2]=0.80, [3]=0.50}, maxwear=0.1, maxlevel=1}
dt_crumbliness = -1.5, }
dt_cuttability = 0.3,
basedurability = 30,
dd_weight = 0,
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
}, },
}) })
minetest.register_tool("default:shovel_stone", { minetest.register_tool("default:shovel_stone", {
description = "Stone Shovel", description = "Stone Shovel",
inventory_image = "default_tool_stoneshovel.png", inventory_image = "default_tool_stoneshovel.png",
tool_digging_properties = { tool_capabilities = {
basetime = 1.5, max_drop_level=0,
dt_weight = 0.5, groupcaps={
dt_crackiness = 2, crumbly={times={[1]=0.80, [2]=0.50, [3]=0.30}, maxwear=0.05, maxlevel=1}
dt_crumbliness = -1.5, }
dt_cuttability = 0.1,
basedurability = 100,
dd_weight = 0,
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
}, },
}) })
minetest.register_tool("default:shovel_steel", { minetest.register_tool("default:shovel_steel", {
description = "Steel Shovel", description = "Steel Shovel",
inventory_image = "default_tool_steelshovel.png", inventory_image = "default_tool_steelshovel.png",
tool_digging_properties = { tool_capabilities = {
basetime = 1.0, max_drop_level=1,
dt_weight = 0.5, groupcaps={
dt_crackiness = 2, crumbly={times={[1]=0.50, [2]=0.35, [3]=0.30}, maxwear=0.1, maxlevel=2}
dt_crumbliness = -1.5, }
dt_cuttability = 0.0,
basedurability = 330,
dd_weight = 0,
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
}, },
}) })
minetest.register_tool("default:axe_wood", { minetest.register_tool("default:axe_wood", {
description = "Wooden Axe", description = "Wooden Axe",
inventory_image = "default_tool_woodaxe.png", inventory_image = "default_tool_woodaxe.png",
tool_digging_properties = { tool_capabilities = {
basetime = 2.0, max_drop_level=0,
dt_weight = 0.5, groupcaps={
dt_crackiness = -0.2, choppy={times={[2]=1.50, [3]=0.80}, maxwear=0.1, maxlevel=1},
dt_crumbliness = 1, fleshy={times={[2]=1.50, [3]=0.80}, maxwear=0.1, maxlevel=1}
dt_cuttability = -0.5, }
basedurability = 30,
dd_weight = 0,
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
}, },
}) })
minetest.register_tool("default:axe_stone", { minetest.register_tool("default:axe_stone", {
description = "Stone Axe", description = "Stone Axe",
inventory_image = "default_tool_stoneaxe.png", inventory_image = "default_tool_stoneaxe.png",
tool_digging_properties = { tool_capabilities = {
basetime = 1.5, max_drop_level=0,
dt_weight = 0.5, groupcaps={
dt_crackiness = -0.2, choppy={times={[1]=1.50, [2]=1.00, [3]=0.60}, maxwear=0.05, maxlevel=1},
dt_crumbliness = 1, fleshy={times={[2]=1.30, [3]=0.70}, maxwear=0.05, maxlevel=1}
dt_cuttability = -0.5, }
basedurability = 100,
dd_weight = 0,
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
}, },
}) })
minetest.register_tool("default:axe_steel", { minetest.register_tool("default:axe_steel", {
description = "Steel Axe", description = "Steel Axe",
inventory_image = "default_tool_steelaxe.png", inventory_image = "default_tool_steelaxe.png",
tool_digging_properties = { tool_capabilities = {
basetime = 1.0, max_drop_level=1,
dt_weight = 0.5, groupcaps={
dt_crackiness = -0.2, choppy={times={[1]=1.00, [2]=0.80, [3]=0.50}, maxwear=0.1, maxlevel=2},
dt_crumbliness = 1, fleshy={times={[2]=1.10, [3]=0.60}, maxwear=0.03, maxlevel=1}
dt_cuttability = -0.5, }
basedurability = 330,
dd_weight = 0,
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
}, },
}) })
minetest.register_tool("default:sword_wood", { minetest.register_tool("default:sword_wood", {
description = "Wooden Sword", description = "Wooden Sword",
inventory_image = "default_tool_woodsword.png", inventory_image = "default_tool_woodsword.png",
tool_digging_properties = { tool_capabilities = {
basetime = 3.0, full_punch_interval = 2.0,
dt_weight = 3, max_drop_level=0,
dt_crackiness = 0, groupcaps={
dt_crumbliness = 1, fleshy={times={[2]=1.10, [3]=0.60}, maxwear=0.1, maxlevel=1},
dt_cuttability = -1, snappy={times={[2]=1.00, [3]=0.50}, maxwear=0.1, maxlevel=1},
basedurability = 30, choppy={times={[3]=1.00}, maxwear=0.05, maxlevel=0}
dd_weight = 0, }
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
} }
}) })
minetest.register_tool("default:sword_stone", { minetest.register_tool("default:sword_stone", {
description = "Stone Sword", description = "Stone Sword",
inventory_image = "default_tool_stonesword.png", inventory_image = "default_tool_stonesword.png",
tool_digging_properties = { tool_capabilities = {
basetime = 2.5, full_punch_interval = 2.0,
dt_weight = 3, max_drop_level=0,
dt_crackiness = 0, groupcaps={
dt_crumbliness = 1, fleshy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1},
dt_cuttability = -1, snappy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1},
basedurability = 100, choppy={times={[3]=0.90}, maxwear=0.05, maxlevel=0}
dd_weight = 0, }
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
} }
}) })
minetest.register_tool("default:sword_steel", { minetest.register_tool("default:sword_steel", {
description = "Steel Sword", description = "Steel Sword",
inventory_image = "default_tool_steelsword.png", inventory_image = "default_tool_steelsword.png",
tool_digging_properties = { tool_capabilities = {
basetime = 2.0, full_punch_interval = 2.0,
dt_weight = 3, max_drop_level=1,
dt_crackiness = 0, groupcaps={
dt_crumbliness = 1, fleshy={times={[1]=1.00, [2]=0.40, [3]=0.20}, maxwear=0.1, maxlevel=2},
dt_cuttability = -1, snappy={times={[2]=0.70, [3]=0.30}, maxwear=0.03, maxlevel=1},
basedurability = 330, choppy={times={[3]=0.70}, maxwear=0.03, maxlevel=0}
dd_weight = 0, }
dd_crackiness = 0,
dd_crumbliness = 0,
dd_cuttability = 0,
} }
}) })
@ -1110,7 +1038,7 @@ minetest.register_node("default:stone", {
description = "Stone", description = "Stone",
tile_images = {"default_stone.png"}, tile_images = {"default_stone.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_stonelike(1.0), groups = {cracky=3},
drop = 'default:cobble', drop = 'default:cobble',
legacy_mineral = true, legacy_mineral = true,
}) })
@ -1119,7 +1047,7 @@ minetest.register_node("default:stone_with_coal", {
description = "Stone with coal", description = "Stone with coal",
tile_images = {"default_stone.png^default_mineral_coal.png"}, tile_images = {"default_stone.png^default_mineral_coal.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_stonelike(1.0), groups = {cracky=3},
drop = 'default:coal_lump', drop = 'default:coal_lump',
}) })
@ -1127,7 +1055,7 @@ minetest.register_node("default:stone_with_iron", {
description = "Stone with iron", description = "Stone with iron",
tile_images = {"default_stone.png^default_mineral_iron.png"}, tile_images = {"default_stone.png^default_mineral_iron.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_stonelike(1.0), groups = {cracky=3},
drop = 'default:iron_lump', drop = 'default:iron_lump',
}) })
@ -1135,7 +1063,7 @@ minetest.register_node("default:dirt_with_grass", {
description = "Dirt with grass", description = "Dirt with grass",
tile_images = {"default_grass.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"}, tile_images = {"default_grass.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_dirtlike(1.0), groups = {crumbly=3},
drop = 'default:dirt', drop = 'default:dirt',
}) })
@ -1143,7 +1071,7 @@ minetest.register_node("default:dirt_with_grass_footsteps", {
description = "Dirt with grass and footsteps", description = "Dirt with grass and footsteps",
tile_images = {"default_grass_footsteps.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"}, tile_images = {"default_grass_footsteps.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_dirtlike(1.0), groups = {crumbly=3},
drop = 'default:dirt', drop = 'default:dirt',
}) })
@ -1151,28 +1079,28 @@ minetest.register_node("default:dirt", {
description = "Dirt", description = "Dirt",
tile_images = {"default_dirt.png"}, tile_images = {"default_dirt.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_dirtlike(1.0), groups = {crumbly=3},
}) })
minetest.register_node("default:sand", { minetest.register_node("default:sand", {
description = "Sand", description = "Sand",
tile_images = {"default_sand.png"}, tile_images = {"default_sand.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_dirtlike(1.0), groups = {crumbly=3},
}) })
minetest.register_node("default:gravel", { minetest.register_node("default:gravel", {
description = "Gravel", description = "Gravel",
tile_images = {"default_gravel.png"}, tile_images = {"default_gravel.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_gravellike(1.0), groups = {crumbly=2},
}) })
minetest.register_node("default:sandstone", { minetest.register_node("default:sandstone", {
description = "Sandstone", description = "Sandstone",
tile_images = {"default_sandstone.png"}, tile_images = {"default_sandstone.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_dirtlike(1.0), -- FIXME should this be stonelike? groups = {crumbly=2,cracky=2},
drop = 'default:sand', drop = 'default:sand',
}) })
@ -1180,7 +1108,7 @@ minetest.register_node("default:clay", {
description = "Clay", description = "Clay",
tile_images = {"default_clay.png"}, tile_images = {"default_clay.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_dirtlike(1.0), groups = {crumbly=3},
drop = 'default:clay_lump 4', drop = 'default:clay_lump 4',
}) })
@ -1188,7 +1116,7 @@ minetest.register_node("default:brick", {
description = "Brick", description = "Brick",
tile_images = {"default_brick.png"}, tile_images = {"default_brick.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_stonelike(1.0), groups = {cracky=3},
drop = 'default:clay_brick 4', drop = 'default:clay_brick 4',
}) })
@ -1196,14 +1124,14 @@ minetest.register_node("default:tree", {
description = "Tree", description = "Tree",
tile_images = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"}, tile_images = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_woodlike(1.0), groups = {snappy=2},
}) })
minetest.register_node("default:jungletree", { minetest.register_node("default:jungletree", {
description = "Jungle Tree", description = "Jungle Tree",
tile_images = {"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"}, tile_images = {"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_woodlike(1.0), groups = {snappy=2},
}) })
minetest.register_node("default:junglegrass", { minetest.register_node("default:junglegrass", {
@ -1215,7 +1143,7 @@ minetest.register_node("default:junglegrass", {
wield_image = "default_junglegrass.png", wield_image = "default_junglegrass.png",
paramtype = "light", paramtype = "light",
walkable = false, walkable = false,
material = minetest.digprop_leaveslike(1.0), groups = {snappy=3},
}) })
minetest.register_node("default:leaves", { minetest.register_node("default:leaves", {
@ -1224,7 +1152,7 @@ minetest.register_node("default:leaves", {
visual_scale = 1.3, visual_scale = 1.3,
tile_images = {"default_leaves.png"}, tile_images = {"default_leaves.png"},
paramtype = "light", paramtype = "light",
material = minetest.digprop_leaveslike(1.0), groups = {snappy=3},
drop = { drop = {
max_items = 1, max_items = 1,
items = { items = {
@ -1246,7 +1174,7 @@ minetest.register_node("default:cactus", {
description = "Cactus", description = "Cactus",
tile_images = {"default_cactus_top.png", "default_cactus_top.png", "default_cactus_side.png"}, tile_images = {"default_cactus_top.png", "default_cactus_top.png", "default_cactus_side.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_woodlike(0.75), groups = {snappy=2},
}) })
minetest.register_node("default:papyrus", { minetest.register_node("default:papyrus", {
@ -1258,14 +1186,14 @@ minetest.register_node("default:papyrus", {
paramtype = "light", paramtype = "light",
is_ground_content = true, is_ground_content = true,
walkable = false, walkable = false,
material = minetest.digprop_leaveslike(0.5), groups = {snappy=3},
}) })
minetest.register_node("default:bookshelf", { minetest.register_node("default:bookshelf", {
description = "Bookshelf", description = "Bookshelf",
tile_images = {"default_wood.png", "default_wood.png", "default_bookshelf.png"}, tile_images = {"default_wood.png", "default_wood.png", "default_bookshelf.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_woodlike(0.75), groups = {snappy=2},
}) })
minetest.register_node("default:glass", { minetest.register_node("default:glass", {
@ -1276,7 +1204,7 @@ minetest.register_node("default:glass", {
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_glasslike(1.0), groups = {snappy=2,cracky=3},
}) })
minetest.register_node("default:fence_wood", { minetest.register_node("default:fence_wood", {
@ -1291,7 +1219,7 @@ minetest.register_node("default:fence_wood", {
type = "fixed", type = "fixed",
fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7}, fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7},
}, },
material = minetest.digprop_woodlike(0.75), groups = {snappy=2},
}) })
minetest.register_node("default:rail", { minetest.register_node("default:rail", {
@ -1307,7 +1235,7 @@ minetest.register_node("default:rail", {
type = "fixed", type = "fixed",
--fixed = <default> --fixed = <default>
}, },
material = minetest.digprop_dirtlike(0.75), groups = {bendy=2,snappy=1},
}) })
minetest.register_node("default:ladder", { minetest.register_node("default:ladder", {
@ -1327,7 +1255,7 @@ minetest.register_node("default:ladder", {
--wall_bottom = = <default> --wall_bottom = = <default>
--wall_side = = <default> --wall_side = = <default>
}, },
material = minetest.digprop_woodlike(0.5), groups = {snappy=2},
legacy_wallmounted = true, legacy_wallmounted = true,
}) })
@ -1335,14 +1263,14 @@ minetest.register_node("default:wood", {
description = "Wood", description = "Wood",
tile_images = {"default_wood.png"}, tile_images = {"default_wood.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_woodlike(0.75), groups = {snappy=2},
}) })
minetest.register_node("default:mese", { minetest.register_node("default:mese", {
description = "Mese", description = "Mese",
tile_images = {"default_mese.png"}, tile_images = {"default_mese.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_stonelike(0.5), groups = {cracky=1},
}) })
minetest.register_node("default:cloud", { minetest.register_node("default:cloud", {
@ -1371,6 +1299,7 @@ minetest.register_node("default:water_flowing", {
{image="default_water.png", backface_culling=false}, {image="default_water.png", backface_culling=false},
{image="default_water.png", backface_culling=true}, {image="default_water.png", backface_culling=true},
}, },
groups = {water=3, liquid=3},
}) })
minetest.register_node("default:water_source", { minetest.register_node("default:water_source", {
@ -1393,6 +1322,7 @@ minetest.register_node("default:water_source", {
-- New-style water source material (mostly unused) -- New-style water source material (mostly unused)
{image="default_water.png", backface_culling=false}, {image="default_water.png", backface_culling=false},
}, },
groups = {water=3, liquid=3},
}) })
minetest.register_node("default:lava_flowing", { minetest.register_node("default:lava_flowing", {
@ -1416,6 +1346,7 @@ minetest.register_node("default:lava_flowing", {
{image="default_lava.png", backface_culling=false}, {image="default_lava.png", backface_culling=false},
{image="default_lava.png", backface_culling=true}, {image="default_lava.png", backface_culling=true},
}, },
groups = {lava=3, liquid=2, hot=3},
}) })
minetest.register_node("default:lava_source", { minetest.register_node("default:lava_source", {
@ -1439,6 +1370,7 @@ minetest.register_node("default:lava_source", {
-- New-style lava source material (mostly unused) -- New-style lava source material (mostly unused)
{image="default_lava.png", backface_culling=false}, {image="default_lava.png", backface_culling=false},
}, },
groups = {lava=3, liquid=2, hot=3},
}) })
minetest.register_node("default:torch", { minetest.register_node("default:torch", {
@ -1458,7 +1390,7 @@ minetest.register_node("default:torch", {
wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1}, wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1}, wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
}, },
material = minetest.digprop_constanttime(0.0), groups = {dig_immediate=1},
legacy_wallmounted = true, legacy_wallmounted = true,
}) })
@ -1479,7 +1411,7 @@ minetest.register_node("default:sign_wall", {
--wall_bottom = <default> --wall_bottom = <default>
--wall_side = <default> --wall_side = <default>
}, },
material = minetest.digprop_constanttime(0.5), groups = {dig_immediate=2},
legacy_wallmounted = true, legacy_wallmounted = true,
}) })
@ -1489,7 +1421,7 @@ minetest.register_node("default:chest", {
"default_chest_side.png", "default_chest_side.png", "default_chest_front.png"}, "default_chest_side.png", "default_chest_side.png", "default_chest_front.png"},
paramtype2 = "facedir", paramtype2 = "facedir",
metadata_name = "chest", metadata_name = "chest",
material = minetest.digprop_woodlike(1.0), groups = {snappy=2},
legacy_facedir_simple = true, legacy_facedir_simple = true,
}) })
@ -1499,7 +1431,7 @@ minetest.register_node("default:chest_locked", {
"default_chest_side.png", "default_chest_side.png", "default_chest_lock.png"}, "default_chest_side.png", "default_chest_side.png", "default_chest_lock.png"},
paramtype2 = "facedir", paramtype2 = "facedir",
metadata_name = "locked_chest", metadata_name = "locked_chest",
material = minetest.digprop_woodlike(1.0), groups = {snappy=2},
legacy_facedir_simple = true, legacy_facedir_simple = true,
}) })
@ -1509,7 +1441,7 @@ minetest.register_node("default:furnace", {
"default_furnace_side.png", "default_furnace_side.png", "default_furnace_front.png"}, "default_furnace_side.png", "default_furnace_side.png", "default_furnace_front.png"},
paramtype2 = "facedir", paramtype2 = "facedir",
metadata_name = "furnace", metadata_name = "furnace",
material = minetest.digprop_stonelike(3.0), groups = {cracky=2},
legacy_facedir_simple = true, legacy_facedir_simple = true,
}) })
@ -1517,21 +1449,21 @@ minetest.register_node("default:cobble", {
description = "Cobble", description = "Cobble",
tile_images = {"default_cobble.png"}, tile_images = {"default_cobble.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_stonelike(0.9), groups = {cracky=3},
}) })
minetest.register_node("default:mossycobble", { minetest.register_node("default:mossycobble", {
description = "Mossy Cobble", description = "Mossy Cobble",
tile_images = {"default_mossycobble.png"}, tile_images = {"default_mossycobble.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_stonelike(0.8), groups = {cracky=3},
}) })
minetest.register_node("default:steelblock", { minetest.register_node("default:steelblock", {
description = "Steel Block", description = "Steel Block",
tile_images = {"default_steel_block.png"}, tile_images = {"default_steel_block.png"},
is_ground_content = true, is_ground_content = true,
material = minetest.digprop_stonelike(5.0), groups = {snappy=1,bendy=2},
}) })
minetest.register_node("default:nyancat", { minetest.register_node("default:nyancat", {
@ -1540,7 +1472,7 @@ minetest.register_node("default:nyancat", {
"default_nc_side.png", "default_nc_back.png", "default_nc_front.png"}, "default_nc_side.png", "default_nc_back.png", "default_nc_front.png"},
inventory_image = "default_nc_front.png", inventory_image = "default_nc_front.png",
paramtype2 = "facedir", paramtype2 = "facedir",
material = minetest.digprop_stonelike(3.0), groups = {cracky=2},
legacy_facedir_simple = true, legacy_facedir_simple = true,
}) })
@ -1548,7 +1480,7 @@ minetest.register_node("default:nyancat_rainbow", {
description = "Nyancat Rainbow", description = "Nyancat Rainbow",
tile_images = {"default_nc_rb.png"}, tile_images = {"default_nc_rb.png"},
inventory_image = "default_nc_rb.png", inventory_image = "default_nc_rb.png",
material = minetest.digprop_stonelike(3.0), groups = {cracky=2},
}) })
minetest.register_node("default:sapling", { minetest.register_node("default:sapling", {
@ -1560,7 +1492,7 @@ minetest.register_node("default:sapling", {
wield_image = "default_sapling.png", wield_image = "default_sapling.png",
paramtype = "light", paramtype = "light",
walkable = false, walkable = false,
material = minetest.digprop_constanttime(0.0), groups = {dig_immediate=1},
}) })
minetest.register_node("default:apple", { minetest.register_node("default:apple", {
@ -1572,7 +1504,7 @@ minetest.register_node("default:apple", {
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
walkable = false, walkable = false,
material = minetest.digprop_constanttime(0.0), groups = {dig_immediate=1},
on_use = minetest.item_eat(4), on_use = minetest.item_eat(4),
}) })

@ -116,7 +116,7 @@ set(common_SRCS
serverobject.cpp serverobject.cpp
noise.cpp noise.cpp
porting.cpp porting.cpp
materials.cpp tool.cpp
defaultsettings.cpp defaultsettings.cpp
mapnode.cpp mapnode.cpp
voxel.cpp voxel.cpp

@ -44,9 +44,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Obsolete TOCLIENT_TOOLDEF Obsolete TOCLIENT_TOOLDEF
Obsolete TOCLIENT_CRAFTITEMDEF Obsolete TOCLIENT_CRAFTITEMDEF
Compress the contents of TOCLIENT_ITEMDEF and TOCLIENT_NODEDEF Compress the contents of TOCLIENT_ITEMDEF and TOCLIENT_NODEDEF
PROTOCOL_VERSION 8:
Digging based on item groups
*/ */
#define PROTOCOL_VERSION 7 #define PROTOCOL_VERSION 8
#define PROTOCOL_ID 0x4f457403 #define PROTOCOL_ID 0x4f457403

@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "main.h" // For g_profiler #include "main.h" // For g_profiler
#include "profiler.h" #include "profiler.h"
#include "serialization.h" // For compressZlib #include "serialization.h" // For compressZlib
#include "materials.h" // For MaterialProperties and ToolDiggingProperties #include "tool.h" // For ToolCapabilities
#include "gamedef.h" #include "gamedef.h"
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types; core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
@ -723,24 +723,23 @@ void Oerkki1SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize(); v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
m_speed_f += dir*12*BS; m_speed_f += dir*12*BS;
// "Material" properties of an oerkki // "Material" groups of the object
MaterialProperties mp; std::map<std::string, int> groups;
mp.diggability = DIGGABLE_NORMAL; groups["snappy"] = 1;
mp.crackiness = -1.0; groups["choppy"] = 1;
mp.cuttability = 1.0; groups["fleshy"] = 3;
IItemDefManager *idef = m_env->getGameDef()->idef(); IItemDefManager *idef = m_env->getGameDef()->idef();
ItemStack punchitem = puncher->getWieldedItem(); ItemStack punchitem = puncher->getWieldedItem();
ToolDiggingProperties tp = ToolCapabilities tp = punchitem.getToolCapabilities(idef);
punchitem.getToolDiggingProperties(idef);
HittingProperties hitprop = getHittingProperties(&mp, &tp, HitParams hit_params = getHitParams(groups, &tp,
time_from_last_punch); time_from_last_punch);
doDamage(hitprop.hp); doDamage(hit_params.hp);
if(g_settings->getBool("creative_mode") == false) if(g_settings->getBool("creative_mode") == false)
{ {
punchitem.addWear(hitprop.wear, idef); punchitem.addWear(hit_params.wear, idef);
puncher->setWieldedItem(punchitem); puncher->setWieldedItem(punchitem);
} }
} }
@ -1419,24 +1418,23 @@ void MobV2SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
sendPosition(); sendPosition();
// "Material" properties of the MobV2 // "Material" groups of the object
MaterialProperties mp; std::map<std::string, int> groups;
mp.diggability = DIGGABLE_NORMAL; groups["snappy"] = 1;
mp.crackiness = -1.0; groups["choppy"] = 1;
mp.cuttability = 1.0; groups["fleshy"] = 3;
IItemDefManager *idef = m_env->getGameDef()->idef(); IItemDefManager *idef = m_env->getGameDef()->idef();
ItemStack punchitem = puncher->getWieldedItem(); ItemStack punchitem = puncher->getWieldedItem();
ToolDiggingProperties tp = ToolCapabilities tp = punchitem.getToolCapabilities(idef);
punchitem.getToolDiggingProperties(idef);
HittingProperties hitprop = getHittingProperties(&mp, &tp, HitParams hit_params = getHitParams(groups, &tp,
time_from_last_punch); time_from_last_punch);
doDamage(hitprop.hp); doDamage(hit_params.hp);
if(g_settings->getBool("creative_mode") == false) if(g_settings->getBool("creative_mode") == false)
{ {
punchitem.addWear(hitprop.wear, idef); punchitem.addWear(hit_params.wear, idef);
puncher->setWieldedItem(punchitem); puncher->setWieldedItem(punchitem);
} }
} }
@ -1504,7 +1502,8 @@ void MobV2SAO::updateProperties()
void MobV2SAO::doDamage(u16 d) void MobV2SAO::doDamage(u16 d)
{ {
infostream<<"MobV2 hp="<<m_hp<<" damage="<<d<<std::endl; if(d > 0)
actionstream<<"MobV2 ("<<m_hp<<"hp) takes "<<d<<"hp of damage"<<std::endl;
if(d < m_hp) if(d < m_hp)
{ {

@ -31,7 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "guiInventoryMenu.h" #include "guiInventoryMenu.h"
#include "guiTextInputMenu.h" #include "guiTextInputMenu.h"
#include "guiDeathScreen.h" #include "guiDeathScreen.h"
#include "materials.h" #include "tool.h"
#include "config.h" #include "config.h"
#include "clouds.h" #include "clouds.h"
#include "camera.h" #include "camera.h"
@ -1935,21 +1935,26 @@ void the_game(
MapNode n = client.getNode(nodepos); MapNode n = client.getNode(nodepos);
// Get digging properties for material and tool // Get digging properties for material and tool
MaterialProperties mp = nodedef->get(n.getContent()).material; ToolCapabilities tp = playeritem.getToolCapabilities(itemdef);
ToolDiggingProperties tp = DigParams params = getDigParams(nodedef->get(n).groups, &tp);
playeritem.getToolDiggingProperties(itemdef); // If can't dig, try hand
DiggingProperties prop = getDiggingProperties(&mp, &tp); if(!params.diggable){
const ItemDefinition &hand = itemdef->get("");
const ToolCapabilities *tp = hand.tool_capabilities;
if(tp)
params = getDigParams(nodedef->get(n).groups, tp);
}
float dig_time_complete = 0.0; float dig_time_complete = 0.0;
if(prop.diggable == false) if(params.diggable == false)
{ {
// I guess nobody will wait for this long // I guess nobody will wait for this long
dig_time_complete = 10000000.0; dig_time_complete = 10000000.0;
} }
else else
{ {
dig_time_complete = prop.time; dig_time_complete = params.time;
} }
if(dig_time_complete >= 0.001) if(dig_time_complete >= 0.001)

@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "debug.h" #include "debug.h"
#include "itemdef.h" #include "itemdef.h"
struct ToolDiggingProperties; struct ToolCapabilities;
struct ItemStack struct ItemStack
{ {
@ -107,15 +107,15 @@ struct ItemStack
} }
// Get tool digging properties, or those of the hand if not a tool // Get tool digging properties, or those of the hand if not a tool
const ToolDiggingProperties& getToolDiggingProperties( const ToolCapabilities& getToolCapabilities(
IItemDefManager *itemdef) const IItemDefManager *itemdef) const
{ {
ToolDiggingProperties *prop; ToolCapabilities *cap;
prop = itemdef->get(name).tool_digging_properties; cap = itemdef->get(name).tool_capabilities;
if(prop == NULL) if(cap == NULL)
prop = itemdef->get("").tool_digging_properties; cap = itemdef->get("").tool_capabilities;
assert(prop != NULL); assert(cap != NULL);
return *prop; return *cap;
} }
// Wear out (only tools) // Wear out (only tools)

@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "gamedef.h" #include "gamedef.h"
#include "nodedef.h" #include "nodedef.h"
#include "materials.h" #include "tool.h"
#include "inventory.h" #include "inventory.h"
#ifndef SERVER #ifndef SERVER
#include "mapblock_mesh.h" #include "mapblock_mesh.h"
@ -64,11 +64,12 @@ ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
stack_max = def.stack_max; stack_max = def.stack_max;
usable = def.usable; usable = def.usable;
liquids_pointable = def.liquids_pointable; liquids_pointable = def.liquids_pointable;
if(def.tool_digging_properties) if(def.tool_capabilities)
{ {
tool_digging_properties = new ToolDiggingProperties( tool_capabilities = new ToolCapabilities(
*def.tool_digging_properties); *def.tool_capabilities);
} }
groups = def.groups;
#ifndef SERVER #ifndef SERVER
inventory_texture = def.inventory_texture; inventory_texture = def.inventory_texture;
if(def.wield_mesh) if(def.wield_mesh)
@ -88,7 +89,7 @@ ItemDefinition::~ItemDefinition()
void ItemDefinition::resetInitial() void ItemDefinition::resetInitial()
{ {
// Initialize pointers to NULL so reset() does not delete undefined pointers // Initialize pointers to NULL so reset() does not delete undefined pointers
tool_digging_properties = NULL; tool_capabilities = NULL;
#ifndef SERVER #ifndef SERVER
inventory_texture = NULL; inventory_texture = NULL;
wield_mesh = NULL; wield_mesh = NULL;
@ -107,11 +108,12 @@ void ItemDefinition::reset()
stack_max = 99; stack_max = 99;
usable = false; usable = false;
liquids_pointable = false; liquids_pointable = false;
if(tool_digging_properties) if(tool_capabilities)
{ {
delete tool_digging_properties; delete tool_capabilities;
tool_digging_properties = NULL; tool_capabilities = NULL;
} }
groups.clear();
#ifndef SERVER #ifndef SERVER
inventory_texture = NULL; inventory_texture = NULL;
@ -125,7 +127,7 @@ void ItemDefinition::reset()
void ItemDefinition::serialize(std::ostream &os) const void ItemDefinition::serialize(std::ostream &os) const
{ {
writeU8(os, 0); // version writeU8(os, 1); // version
writeU8(os, type); writeU8(os, type);
os<<serializeString(name); os<<serializeString(name);
os<<serializeString(description); os<<serializeString(description);
@ -135,14 +137,19 @@ void ItemDefinition::serialize(std::ostream &os) const
writeS16(os, stack_max); writeS16(os, stack_max);
writeU8(os, usable); writeU8(os, usable);
writeU8(os, liquids_pointable); writeU8(os, liquids_pointable);
std::string tool_digging_properties_s = ""; std::string tool_capabilities_s = "";
if(tool_digging_properties) if(tool_capabilities){
{
std::ostringstream tmp_os(std::ios::binary); std::ostringstream tmp_os(std::ios::binary);
tool_digging_properties->serialize(tmp_os); tool_capabilities->serialize(tmp_os);
tool_digging_properties_s = tmp_os.str(); tool_capabilities_s = tmp_os.str();
}
os<<serializeString(tool_capabilities_s);
writeU16(os, groups.size());
for(std::map<std::string, int>::const_iterator
i = groups.begin(); i != groups.end(); i++){
os<<serializeString(i->first);
writeS16(os, i->second);
} }
os<<serializeString(tool_digging_properties_s);
} }
void ItemDefinition::deSerialize(std::istream &is) void ItemDefinition::deSerialize(std::istream &is)
@ -152,7 +159,7 @@ void ItemDefinition::deSerialize(std::istream &is)
// Deserialize // Deserialize
int version = readU8(is); int version = readU8(is);
if(version != 0) if(version != 1)
throw SerializationError("unsupported ItemDefinition version"); throw SerializationError("unsupported ItemDefinition version");
type = (enum ItemType)readU8(is); type = (enum ItemType)readU8(is);
name = deSerializeString(is); name = deSerializeString(is);
@ -163,12 +170,19 @@ void ItemDefinition::deSerialize(std::istream &is)
stack_max = readS16(is); stack_max = readS16(is);
usable = readU8(is); usable = readU8(is);
liquids_pointable = readU8(is); liquids_pointable = readU8(is);
std::string tool_digging_properties_s = deSerializeString(is); std::string tool_capabilities_s = deSerializeString(is);
if(!tool_digging_properties_s.empty()) if(!tool_capabilities_s.empty())
{ {
std::istringstream tmp_is(tool_digging_properties_s, std::ios::binary); std::istringstream tmp_is(tool_capabilities_s, std::ios::binary);
tool_digging_properties = new ToolDiggingProperties; tool_capabilities = new ToolCapabilities;
tool_digging_properties->deSerialize(tmp_is); tool_capabilities->deSerialize(tmp_is);
}
groups.clear();
u32 groups_size = readU16(is);
for(u32 i=0; i<groups_size; i++){
std::string name = deSerializeString(is);
int value = readS16(is);
groups[name] = value;
} }
} }
@ -253,7 +267,7 @@ public:
ItemDefinition* hand_def = new ItemDefinition; ItemDefinition* hand_def = new ItemDefinition;
hand_def->name = ""; hand_def->name = "";
hand_def->wield_image = "wieldhand.png"; hand_def->wield_image = "wieldhand.png";
hand_def->tool_digging_properties = new ToolDiggingProperties; hand_def->tool_capabilities = new ToolCapabilities;
m_item_definitions.insert(std::make_pair("", hand_def)); m_item_definitions.insert(std::make_pair("", hand_def));
ItemDefinition* unknown_def = new ItemDefinition; ItemDefinition* unknown_def = new ItemDefinition;
@ -273,9 +287,9 @@ public:
virtual void registerItem(const ItemDefinition &def) virtual void registerItem(const ItemDefinition &def)
{ {
infostream<<"ItemDefManager: registering \""<<def.name<<"\""<<std::endl; infostream<<"ItemDefManager: registering \""<<def.name<<"\""<<std::endl;
// Ensure that the "" item (the hand) always has ToolDiggingProperties // Ensure that the "" item (the hand) always has ToolCapabilities
if(def.name == "") if(def.name == "")
assert(def.tool_digging_properties != NULL); assert(def.tool_capabilities != NULL);
m_item_definitions[def.name] = new ItemDefinition(def); m_item_definitions[def.name] = new ItemDefinition(def);

@ -25,8 +25,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <set> #include <set>
#include <map>
class IGameDef; class IGameDef;
struct ToolDiggingProperties; struct ToolCapabilities;
/*
Some helpers
*/
static inline int itemgroup_get(const std::map<std::string, int> &groups,
const std::string &name)
{
std::map<std::string, int>::const_iterator i = groups.find(name);
if(i == groups.end())
return 0;
return i->second;
}
/* /*
Base item definition Base item definition
@ -63,7 +77,8 @@ struct ItemDefinition
bool usable; bool usable;
bool liquids_pointable; bool liquids_pointable;
// May be NULL. If non-NULL, deleted by destructor // May be NULL. If non-NULL, deleted by destructor
ToolDiggingProperties *tool_digging_properties; ToolCapabilities *tool_capabilities;
std::map<std::string, int> groups;
/* /*
Cached stuff Cached stuff

@ -399,7 +399,6 @@ Doing currently:
#include "filesys.h" #include "filesys.h"
#include "config.h" #include "config.h"
#include "guiMainMenu.h" #include "guiMainMenu.h"
#include "materials.h"
#include "game.h" #include "game.h"
#include "keycode.h" #include "keycode.h"
#include "tile.h" #include "tile.h"

@ -1,159 +0,0 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "materials.h"
#include "utility.h"
void MaterialProperties::serialize(std::ostream &os)
{
writeU8(os, 0); // version
writeU8(os, diggability);
writeF1000(os, constant_time);
writeF1000(os, weight);
writeF1000(os, crackiness);
writeF1000(os, crumbliness);
writeF1000(os, cuttability);
writeF1000(os, flammability);
}
void MaterialProperties::deSerialize(std::istream &is)
{
int version = readU8(is);
if(version != 0)
throw SerializationError("unsupported MaterialProperties version");
diggability = (enum Diggability)readU8(is);
constant_time = readF1000(is);
weight = readF1000(is);
crackiness = readF1000(is);
crumbliness = readF1000(is);
cuttability = readF1000(is);
flammability = readF1000(is);
}
ToolDiggingProperties::ToolDiggingProperties(float full_punch_interval_,
float a, float b, float c, float d, float e,
float f, float g, float h, float i, float j):
full_punch_interval(full_punch_interval_),
basetime(a),
dt_weight(b),
dt_crackiness(c),
dt_crumbliness(d),
dt_cuttability(e),
basedurability(f),
dd_weight(g),
dd_crackiness(h),
dd_crumbliness(i),
dd_cuttability(j)
{}
void ToolDiggingProperties::serialize(std::ostream &os)
{
writeU8(os, 0); // version
writeF1000(os, full_punch_interval);
writeF1000(os, basetime);
writeF1000(os, dt_weight);
writeF1000(os, dt_crackiness);
writeF1000(os, dt_crumbliness);
writeF1000(os, dt_cuttability);
writeF1000(os, basedurability);
writeF1000(os, dd_weight);
writeF1000(os, dd_crackiness);
writeF1000(os, dd_crumbliness);
writeF1000(os, dd_cuttability);
}
void ToolDiggingProperties::deSerialize(std::istream &is)
{
int version = readU8(is);
if(version != 0) throw SerializationError(
"unsupported ToolDiggingProperties version");
full_punch_interval = readF1000(is);
basetime = readF1000(is);
dt_weight = readF1000(is);
dt_crackiness = readF1000(is);
dt_crumbliness = readF1000(is);
dt_cuttability = readF1000(is);
basedurability = readF1000(is);
dd_weight = readF1000(is);
dd_crackiness = readF1000(is);
dd_crumbliness = readF1000(is);
dd_cuttability = readF1000(is);
}
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
const ToolDiggingProperties *tp, float time_from_last_punch)
{
if(mp->diggability == DIGGABLE_NOT)
return DiggingProperties(false, 0, 0);
if(mp->diggability == DIGGABLE_CONSTANT)
return DiggingProperties(true, mp->constant_time, 0);
float time = tp->basetime;
time += tp->dt_weight * mp->weight;
time += tp->dt_crackiness * mp->crackiness;
time += tp->dt_crumbliness * mp->crumbliness;
time += tp->dt_cuttability * mp->cuttability;
if(time < 0.2)
time = 0.2;
float durability = tp->basedurability;
durability += tp->dd_weight * mp->weight;
durability += tp->dd_crackiness * mp->crackiness;
durability += tp->dd_crumbliness * mp->crumbliness;
durability += tp->dd_cuttability * mp->cuttability;
if(durability < 1)
durability = 1;
if(time_from_last_punch < tp->full_punch_interval){
float f = time_from_last_punch / tp->full_punch_interval;
time /= f;
durability /= f;
}
float wear = 1.0 / durability;
u16 wear_i = 65535.*wear;
return DiggingProperties(true, time, wear_i);
}
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
const ToolDiggingProperties *tp)
{
return getDiggingProperties(mp, tp, 1000000);
}
HittingProperties getHittingProperties(const MaterialProperties *mp,
const ToolDiggingProperties *tp, float time_from_last_punch)
{
DiggingProperties digprop = getDiggingProperties(mp, tp,
time_from_last_punch);
// If digging time would be 1 second, 2 hearts go in 1 second.
s16 hp = 2.0 * 2.0 / digprop.time;
// Wear is the same as for digging a single node
s16 wear = (float)digprop.wear;
return HittingProperties(hp, wear);
}
HittingProperties getHittingProperties(const MaterialProperties *mp,
const ToolDiggingProperties *tp)
{
return getHittingProperties(mp, tp, 1000000);
}

@ -1,137 +0,0 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MATERIALS_HEADER
#define MATERIALS_HEADER
/*
Material properties
*/
#include "common_irrlicht.h"
#include <string>
#include <iostream>
enum Diggability
{
DIGGABLE_NOT,
DIGGABLE_NORMAL,
DIGGABLE_CONSTANT
};
struct MaterialProperties
{
// Values can be anything. 0 is normal.
enum Diggability diggability;
// Constant time for DIGGABLE_CONSTANT
float constant_time;
// Weight; the amount of stuff in the block. Not realistic.
float weight;
// Rock; wood a bit.
// A Pickaxe manages high crackiness well.
float crackiness;
// Sand is extremely crumble; dirt is quite crumble.
// A shovel is good for crumbly stuff. Pickaxe is horrible.
float crumbliness;
// An axe is best for cuttable heavy stuff.
// Sword is best for cuttable light stuff.
float cuttability;
// If high, ignites easily
float flammability;
MaterialProperties():
diggability(DIGGABLE_NOT),
constant_time(0.5),
weight(0),
crackiness(0),
crumbliness(0),
cuttability(0),
flammability(0)
{}
void serialize(std::ostream &os);
void deSerialize(std::istream &is);
};
struct ToolDiggingProperties
{
// time = basetime + sum(feature here * feature in MaterialProperties)
float full_punch_interval;
float basetime;
float dt_weight;
float dt_crackiness;
float dt_crumbliness;
float dt_cuttability;
float basedurability;
float dd_weight;
float dd_crackiness;
float dd_crumbliness;
float dd_cuttability;
ToolDiggingProperties(float full_punch_interval_=2.0,
float a=0.75, float b=0, float c=0, float d=0, float e=0,
float f=50, float g=0, float h=0, float i=0, float j=0);
void serialize(std::ostream &os);
void deSerialize(std::istream &is);
};
struct DiggingProperties
{
bool diggable;
// Digging time in seconds
float time;
// Caused wear
u16 wear;
DiggingProperties(bool a_diggable=false, float a_time=0, u16 a_wear=0):
diggable(a_diggable),
time(a_time),
wear(a_wear)
{}
};
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
const ToolDiggingProperties *tp, float time_from_last_punch);
DiggingProperties getDiggingProperties(const MaterialProperties *mp,
const ToolDiggingProperties *tp);
struct HittingProperties
{
s16 hp;
s16 wear;
HittingProperties(s16 hp_=0, s16 wear_=0):
hp(hp_),
wear(wear_)
{}
};
HittingProperties getHittingProperties(const MaterialProperties *mp,
const ToolDiggingProperties *tp, float time_from_last_punch);
HittingProperties getHittingProperties(const MaterialProperties *mp,
const ToolDiggingProperties *tp);
#endif

@ -118,6 +118,7 @@ void ContentFeatures::reset()
in builtin.lua in builtin.lua
*/ */
name = ""; name = "";
groups.clear();
drawtype = NDT_NORMAL; drawtype = NDT_NORMAL;
visual_scale = 1.0; visual_scale = 1.0;
for(u32 i=0; i<6; i++) for(u32 i=0; i<6; i++)
@ -144,18 +145,20 @@ void ContentFeatures::reset()
light_source = 0; light_source = 0;
damage_per_second = 0; damage_per_second = 0;
selection_box = NodeBox(); selection_box = NodeBox();
material = MaterialProperties();
// Make unknown blocks diggable
material.diggability = DIGGABLE_CONSTANT;
material.constant_time = 0.5;
legacy_facedir_simple = false; legacy_facedir_simple = false;
legacy_wallmounted = false; legacy_wallmounted = false;
} }
void ContentFeatures::serialize(std::ostream &os) void ContentFeatures::serialize(std::ostream &os)
{ {
writeU8(os, 1); // version writeU8(os, 2); // version
os<<serializeString(name); os<<serializeString(name);
writeU16(os, groups.size());
for(std::map<std::string, int>::const_iterator
i = groups.begin(); i != groups.end(); i++){
os<<serializeString(i->first);
writeS16(os, i->second);
}
writeU8(os, drawtype); writeU8(os, drawtype);
writeF1000(os, visual_scale); writeF1000(os, visual_scale);
writeU8(os, 6); writeU8(os, 6);
@ -188,7 +191,6 @@ void ContentFeatures::serialize(std::ostream &os)
writeU8(os, light_source); writeU8(os, light_source);
writeU32(os, damage_per_second); writeU32(os, damage_per_second);
selection_box.serialize(os); selection_box.serialize(os);
material.serialize(os);
writeU8(os, legacy_facedir_simple); writeU8(os, legacy_facedir_simple);
writeU8(os, legacy_wallmounted); writeU8(os, legacy_wallmounted);
} }
@ -196,9 +198,16 @@ void ContentFeatures::serialize(std::ostream &os)
void ContentFeatures::deSerialize(std::istream &is) void ContentFeatures::deSerialize(std::istream &is)
{ {
int version = readU8(is); int version = readU8(is);
if(version != 1) if(version != 2)
throw SerializationError("unsupported ContentFeatures version"); throw SerializationError("unsupported ContentFeatures version");
name = deSerializeString(is); name = deSerializeString(is);
groups.clear();
u32 groups_size = readU16(is);
for(u32 i=0; i<groups_size; i++){
std::string name = deSerializeString(is);
int value = readS16(is);
groups[name] = value;
}
drawtype = (enum NodeDrawType)readU8(is); drawtype = (enum NodeDrawType)readU8(is);
visual_scale = readF1000(is); visual_scale = readF1000(is);
if(readU8(is) != 6) if(readU8(is) != 6)
@ -233,7 +242,6 @@ void ContentFeatures::deSerialize(std::istream &is)
light_source = readU8(is); light_source = readU8(is);
damage_per_second = readU32(is); damage_per_second = readU32(is);
selection_box.deSerialize(is); selection_box.deSerialize(is);
material.deSerialize(is);
legacy_facedir_simple = readU8(is); legacy_facedir_simple = readU8(is);
legacy_wallmounted = readU8(is); legacy_wallmounted = readU8(is);
} }
@ -412,9 +420,6 @@ public:
assert(name != ""); assert(name != "");
ContentFeatures f; ContentFeatures f;
f.name = name; f.name = name;
// Make unknown blocks diggable
f.material.diggability = DIGGABLE_CONSTANT;
f.material.constant_time = 0.5;
return set(name, f); return set(name, f);
} }
virtual void updateAliases(IItemDefManager *idef) virtual void updateAliases(IItemDefManager *idef)

@ -23,12 +23,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h" #include "common_irrlicht.h"
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <set> #include <map>
#include "mapnode.h" #include "mapnode.h"
#ifndef SERVER #ifndef SERVER
#include "tile.h" #include "tile.h"
#endif #endif
#include "materials.h" // MaterialProperties
class IItemDefManager; class IItemDefManager;
class ITextureSource; class ITextureSource;
class IGameDef; class IGameDef;
@ -149,6 +148,7 @@ struct ContentFeatures
*/ */
std::string name; // "" = undefined node std::string name; // "" = undefined node
std::map<std::string, int> groups; // Same as in itemdef
// Visual definition // Visual definition
enum NodeDrawType drawtype; enum NodeDrawType drawtype;
@ -194,7 +194,6 @@ struct ContentFeatures
u8 light_source; u8 light_source;
u32 damage_per_second; u32 damage_per_second;
NodeBox selection_box; NodeBox selection_box;
MaterialProperties material;
// Compatibility with old maps // Compatibility with old maps
// Set to true if paramtype used to be 'facedir_simple' // Set to true if paramtype used to be 'facedir_simple'
bool legacy_facedir_simple; bool legacy_facedir_simple;

@ -45,6 +45,7 @@ extern "C" {
#include "mapblock.h" // For getNodeBlockPos #include "mapblock.h" // For getNodeBlockPos
#include "content_nodemeta.h" #include "content_nodemeta.h"
#include "utility.h" #include "utility.h"
#include "tool.h"
static void stackDump(lua_State *L, std::ostream &o) static void stackDump(lua_State *L, std::ostream &o)
{ {
@ -416,14 +417,6 @@ struct EnumString es_NodeBoxType[] =
{0, NULL}, {0, NULL},
}; };
struct EnumString es_Diggability[] =
{
{DIGGABLE_NOT, "not"},
{DIGGABLE_NORMAL, "normal"},
{DIGGABLE_CONSTANT, "constant"},
{0, NULL},
};
/* /*
C struct <-> Lua table converter functions C struct <-> Lua table converter functions
*/ */
@ -612,6 +605,7 @@ static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
return box; return box;
} }
#if 0
/* /*
MaterialProperties MaterialProperties
*/ */
@ -630,87 +624,156 @@ static MaterialProperties read_material_properties(
getfloatfield(L, -1, "flammability", prop.flammability); getfloatfield(L, -1, "flammability", prop.flammability);
return prop; return prop;
} }
#endif
/* /*
ToolDiggingProperties Groups
*/
static void read_groups(lua_State *L, int index,
std::map<std::string, int> &result)
{
result.clear();
lua_pushnil(L);
if(index < 0)
index -= 1;
while(lua_next(L, index) != 0){
// key at index -2 and value at index -1
std::string name = luaL_checkstring(L, -2);
int rating = luaL_checkinteger(L, -1);
result[name] = rating;
// removes value, keeps key for next iteration
lua_pop(L, 1);
}
}
/*
ToolCapabilities
*/ */
static ToolDiggingProperties read_tool_digging_properties( static ToolCapabilities read_tool_capabilities(
lua_State *L, int table) lua_State *L, int table)
{ {
ToolDiggingProperties prop; ToolCapabilities toolcap;
getfloatfield(L, table, "full_punch_interval", prop.full_punch_interval); getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
getfloatfield(L, table, "basetime", prop.basetime); getintfield(L, table, "max_drop_level", toolcap.max_drop_level);
getfloatfield(L, table, "dt_weight", prop.dt_weight); lua_getfield(L, table, "groupcaps");
getfloatfield(L, table, "dt_crackiness", prop.dt_crackiness); if(lua_istable(L, -1)){
getfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness); int table_groupcaps = lua_gettop(L);
getfloatfield(L, table, "dt_cuttability", prop.dt_cuttability); lua_pushnil(L);
getfloatfield(L, table, "basedurability", prop.basedurability); while(lua_next(L, table_groupcaps) != 0){
getfloatfield(L, table, "dd_weight", prop.dd_weight); // key at index -2 and value at index -1
getfloatfield(L, table, "dd_crackiness", prop.dd_crackiness); std::string groupname = luaL_checkstring(L, -2);
getfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness); if(lua_istable(L, -1)){
getfloatfield(L, table, "dd_cuttability", prop.dd_cuttability); int table_groupcap = lua_gettop(L);
return prop; // This will be created
ToolGroupCap groupcap;
// Read simple parameters
getfloatfield(L, table_groupcap, "maxwear", groupcap.maxwear);
getintfield(L, table_groupcap, "maxlevel", groupcap.maxlevel);
// Read "times" table
lua_getfield(L, table_groupcap, "times");
if(lua_istable(L, -1)){
int table_times = lua_gettop(L);
lua_pushnil(L);
while(lua_next(L, table_times) != 0){
// key at index -2 and value at index -1
int rating = luaL_checkinteger(L, -2);
float time = luaL_checknumber(L, -1);
groupcap.times[rating] = time;
// removes value, keeps key for next iteration
lua_pop(L, 1);
}
}
lua_pop(L, 1);
// Insert groupcap into toolcap
toolcap.groupcaps[groupname] = groupcap;
}
// removes value, keeps key for next iteration
lua_pop(L, 1);
}
}
lua_pop(L, 1);
return toolcap;
} }
static void set_tool_digging_properties(lua_State *L, int table, static void set_tool_capabilities(lua_State *L, int table,
const ToolDiggingProperties &prop) const ToolCapabilities &toolcap)
{ {
setfloatfield(L, table, "full_punch_interval", prop.full_punch_interval); setfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
setfloatfield(L, table, "basetime", prop.basetime); setintfield(L, table, "max_drop_level", toolcap.max_drop_level);
setfloatfield(L, table, "dt_weight", prop.dt_weight); // Create groupcaps table
setfloatfield(L, table, "dt_crackiness", prop.dt_crackiness); lua_newtable(L);
setfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness); // For each groupcap
setfloatfield(L, table, "dt_cuttability", prop.dt_cuttability); for(std::map<std::string, ToolGroupCap>::const_iterator
setfloatfield(L, table, "basedurability", prop.basedurability); i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){
setfloatfield(L, table, "dd_weight", prop.dd_weight); // Create groupcap table
setfloatfield(L, table, "dd_crackiness", prop.dd_crackiness); lua_newtable(L);
setfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness); const std::string &name = i->first;
setfloatfield(L, table, "dd_cuttability", prop.dd_cuttability); const ToolGroupCap &groupcap = i->second;
// Create subtable "times"
lua_newtable(L);
for(std::map<int, float>::const_iterator
i = groupcap.times.begin(); i != groupcap.times.end(); i++){
int rating = i->first;
float time = i->second;
lua_pushinteger(L, rating);
lua_pushnumber(L, time);
lua_settable(L, -3);
}
// Set subtable "times"
lua_setfield(L, -2, "times");
// Set simple parameters
setfloatfield(L, -1, "maxwear", groupcap.maxwear);
setintfield(L, -1, "maxlevel", groupcap.maxlevel);
// Insert groupcap table into groupcaps table
lua_setfield(L, -2, name.c_str());
}
// Set groupcaps table
lua_setfield(L, -2, "groupcaps");
} }
static void push_tool_digging_properties(lua_State *L, static void push_tool_capabilities(lua_State *L,
const ToolDiggingProperties &prop) const ToolCapabilities &prop)
{ {
lua_newtable(L); lua_newtable(L);
set_tool_digging_properties(L, -1, prop); set_tool_capabilities(L, -1, prop);
} }
/* /*
DiggingProperties DigParams
*/ */
static void set_digging_properties(lua_State *L, int table, static void set_dig_params(lua_State *L, int table,
const DiggingProperties &prop) const DigParams &params)
{ {
setboolfield(L, table, "diggable", prop.diggable); setboolfield(L, table, "diggable", params.diggable);
setfloatfield(L, table, "time", prop.time); setfloatfield(L, table, "time", params.time);
setintfield(L, table, "wear", prop.wear); setintfield(L, table, "wear", params.wear);
} }
static void push_digging_properties(lua_State *L, static void push_dig_params(lua_State *L,
const DiggingProperties &prop) const DigParams &params)
{ {
lua_newtable(L); lua_newtable(L);
set_digging_properties(L, -1, prop); set_dig_params(L, -1, params);
} }
/* /*
HittingProperties HitParams
*/ */
static void set_hitting_properties(lua_State *L, int table, static void set_hit_params(lua_State *L, int table,
const HittingProperties &prop) const HitParams &params)
{ {
setintfield(L, table, "hp", prop.hp); setintfield(L, table, "hp", params.hp);
setintfield(L, table, "wear", prop.wear); setintfield(L, table, "wear", params.wear);
} }
static void push_hitting_properties(lua_State *L, static void push_hit_params(lua_State *L,
const HittingProperties &prop) const HitParams &params)
{ {
lua_newtable(L); lua_newtable(L);
set_hitting_properties(L, -1, prop); set_hit_params(L, -1, params);
} }
/* /*
@ -778,20 +841,26 @@ static ItemDefinition read_item_definition(lua_State *L, int index)
getboolfield(L, index, "liquids_pointable", def.liquids_pointable); getboolfield(L, index, "liquids_pointable", def.liquids_pointable);
lua_getfield(L, index, "tool_digging_properties"); warn_if_field_exists(L, index, "tool_digging_properties",
"deprecated: use tool_capabilities");
lua_getfield(L, index, "tool_capabilities");
if(lua_istable(L, -1)){ if(lua_istable(L, -1)){
def.tool_digging_properties = new ToolDiggingProperties( def.tool_capabilities = new ToolCapabilities(
read_tool_digging_properties(L, -1)); read_tool_capabilities(L, -1));
} }
lua_pop(L, 1);
// If name is "" (hand), ensure there are ToolDiggingProperties // If name is "" (hand), ensure there are ToolCapabilities
// because it will be looked up there whenever any other item has // because it will be looked up there whenever any other item has
// no ToolDiggingProperties // no ToolCapabilities
if(def.name == "" && def.tool_digging_properties == NULL){ if(def.name == "" && def.tool_capabilities == NULL){
def.tool_digging_properties = new ToolDiggingProperties(); def.tool_capabilities = new ToolCapabilities();
} }
lua_getfield(L, index, "groups");
read_groups(L, -1, def.groups);
lua_pop(L, 1);
return def; return def;
} }
@ -805,8 +874,14 @@ static ContentFeatures read_content_features(lua_State *L, int index)
index = lua_gettop(L) + 1 + index; index = lua_gettop(L) + 1 + index;
ContentFeatures f; ContentFeatures f;
/* Name */
getstringfield(L, index, "name", f.name); getstringfield(L, index, "name", f.name);
/* Groups */
lua_getfield(L, index, "groups");
read_groups(L, -1, f.groups);
lua_pop(L, 1);
/* Visual definition */ /* Visual definition */
f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype", es_DrawType, f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype", es_DrawType,
@ -958,12 +1033,6 @@ static ContentFeatures read_content_features(lua_State *L, int index)
} }
lua_pop(L, 1); lua_pop(L, 1);
lua_getfield(L, index, "material");
if(lua_istable(L, -1)){
f.material = read_material_properties(L, -1);
}
lua_pop(L, 1);
// Set to true if paramtype used to be 'facedir_simple' // Set to true if paramtype used to be 'facedir_simple'
getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple); getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
// Set to true if wall_mounted used to be set to true // Set to true if wall_mounted used to be set to true
@ -1215,16 +1284,16 @@ private:
return 1; return 1;
} }
// get_tool_digging_properties(self) -> table // get_tool_capabilities(self) -> table
// Returns the effective tool digging properties. // Returns the effective tool digging properties.
// Returns those of the hand ("") if this item has none associated. // Returns those of the hand ("") if this item has none associated.
static int l_get_tool_digging_properties(lua_State *L) static int l_get_tool_capabilities(lua_State *L)
{ {
LuaItemStack *o = checkobject(L, 1); LuaItemStack *o = checkobject(L, 1);
ItemStack &item = o->m_stack; ItemStack &item = o->m_stack;
const ToolDiggingProperties &prop = const ToolCapabilities &prop =
item.getToolDiggingProperties(get_server(L)->idef()); item.getToolCapabilities(get_server(L)->idef());
push_tool_digging_properties(L, prop); push_tool_capabilities(L, prop);
return 1; return 1;
} }
@ -1386,7 +1455,7 @@ const luaL_reg LuaItemStack::methods[] = {
method(LuaItemStack, get_free_space), method(LuaItemStack, get_free_space),
method(LuaItemStack, is_known), method(LuaItemStack, is_known),
method(LuaItemStack, get_definition), method(LuaItemStack, get_definition),
method(LuaItemStack, get_tool_digging_properties), method(LuaItemStack, get_tool_capabilities),
method(LuaItemStack, add_wear), method(LuaItemStack, add_wear),
method(LuaItemStack, add_item), method(LuaItemStack, add_item),
method(LuaItemStack, item_fits), method(LuaItemStack, item_fits),
@ -3513,28 +3582,30 @@ static int l_get_inventory(lua_State *L)
return 1; return 1;
} }
// get_digging_properties(material_properties, tool_digging_properties[, time_from_last_punch]) // get_dig_params(groups, tool_capabilities[, time_from_last_punch])
static int l_get_digging_properties(lua_State *L) static int l_get_dig_params(lua_State *L)
{ {
MaterialProperties mp = read_material_properties(L, 1); std::map<std::string, int> groups;
ToolDiggingProperties tp = read_tool_digging_properties(L, 2); read_groups(L, 1, groups);
ToolCapabilities tp = read_tool_capabilities(L, 2);
if(lua_isnoneornil(L, 3)) if(lua_isnoneornil(L, 3))
push_digging_properties(L, getDiggingProperties(&mp, &tp)); push_dig_params(L, getDigParams(groups, &tp));
else else
push_digging_properties(L, getDiggingProperties(&mp, &tp, push_dig_params(L, getDigParams(groups, &tp,
luaL_checknumber(L, 3))); luaL_checknumber(L, 3)));
return 1; return 1;
} }
// get_hitting_properties(material_properties, tool_digging_properties[, time_from_last_punch]) // get_hit_params(groups, tool_capabilities[, time_from_last_punch])
static int l_get_hitting_properties(lua_State *L) static int l_get_hit_params(lua_State *L)
{ {
MaterialProperties mp = read_material_properties(L, 1); std::map<std::string, int> groups;
ToolDiggingProperties tp = read_tool_digging_properties(L, 2); read_groups(L, 1, groups);
ToolCapabilities tp = read_tool_capabilities(L, 2);
if(lua_isnoneornil(L, 3)) if(lua_isnoneornil(L, 3))
push_hitting_properties(L, getHittingProperties(&mp, &tp)); push_hit_params(L, getHitParams(groups, &tp));
else else
push_hitting_properties(L, getHittingProperties(&mp, &tp, push_hit_params(L, getHitParams(groups, &tp,
luaL_checknumber(L, 3))); luaL_checknumber(L, 3)));
return 1; return 1;
} }
@ -3580,8 +3651,8 @@ static const struct luaL_Reg minetest_f [] = {
{"chat_send_player", l_chat_send_player}, {"chat_send_player", l_chat_send_player},
{"get_player_privs", l_get_player_privs}, {"get_player_privs", l_get_player_privs},
{"get_inventory", l_get_inventory}, {"get_inventory", l_get_inventory},
{"get_digging_properties", l_get_digging_properties}, {"get_dig_params", l_get_dig_params},
{"get_hitting_properties", l_get_hitting_properties}, {"get_hit_params", l_get_hit_params},
{"get_current_modname", l_get_current_modname}, {"get_current_modname", l_get_current_modname},
{"get_modpath", l_get_modpath}, {"get_modpath", l_get_modpath},
{"get_worldpath", l_get_worldpath}, {"get_worldpath", l_get_worldpath},

@ -27,7 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "main.h" #include "main.h"
#include "constants.h" #include "constants.h"
#include "voxel.h" #include "voxel.h"
#include "materials.h"
#include "config.h" #include "config.h"
#include "servercommand.h" #include "servercommand.h"
#include "filesys.h" #include "filesys.h"

@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serverobject.h" #include "serverobject.h"
#include <fstream> #include <fstream>
#include "inventory.h" #include "inventory.h"
#include "materials.h"
ServerActiveObject::ServerActiveObject(ServerEnvironment *env, v3f pos): ServerActiveObject::ServerActiveObject(ServerEnvironment *env, v3f pos):
ActiveObject(0), ActiveObject(0),

@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "gamedef.h" #include "gamedef.h"
#include "inventory.h" #include "inventory.h"
#include "environment.h" #include "environment.h"
#include "materials.h" #include "tool.h"
ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env): ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env):
Player(env->getGameDef()), Player(env->getGameDef()),
@ -181,35 +181,32 @@ void ServerRemotePlayer::punch(ServerActiveObject *puncher,
return; return;
} }
// "Material" properties of a player // "Material" groups of the player
MaterialProperties mp; std::map<std::string, int> groups;
mp.diggability = DIGGABLE_NORMAL; groups["snappy"] = 1;
mp.crackiness = -0.5; groups["choppy"] = 2;
mp.cuttability = 0.5;
IItemDefManager *idef = m_env->getGameDef()->idef(); IItemDefManager *idef = m_env->getGameDef()->idef();
ItemStack punchitem = puncher->getWieldedItem(); ItemStack punchitem = puncher->getWieldedItem();
ToolDiggingProperties tp = ToolCapabilities tp = punchitem.getToolCapabilities(idef);
punchitem.getToolDiggingProperties(idef);
HittingProperties hitprop = getHittingProperties(&mp, &tp, HitParams hitparams = getHitParams(groups, &tp, time_from_last_punch);
time_from_last_punch);
actionstream<<"Player "<<getName()<<" punched by " actionstream<<"Player "<<getName()<<" punched by "
<<puncher->getDescription()<<", damage "<<hitprop.hp <<puncher->getDescription()<<", damage "<<hitparams.hp
<<" HP"<<std::endl; <<" HP"<<std::endl;
setHP(getHP() - hitprop.hp); setHP(getHP() - hitparams.hp);
punchitem.addWear(hitprop.wear, idef); punchitem.addWear(hitparams.wear, idef);
puncher->setWieldedItem(punchitem); puncher->setWieldedItem(punchitem);
if(hitprop.hp != 0) if(hitparams.hp != 0)
{ {
std::ostringstream os(std::ios::binary); std::ostringstream os(std::ios::binary);
// command (1 = punched) // command (1 = punched)
writeU8(os, 1); writeU8(os, 1);
// damage // damage
writeS16(os, hitprop.hp); writeS16(os, hitparams.hp);
// create message and add to list // create message and add to list
ActiveObjectMessage aom(getId(), false, os.str()); ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom); m_messages_out.push_back(aom);

@ -68,6 +68,7 @@ void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *n
itemdef.type = ITEM_NODE; itemdef.type = ITEM_NODE;
itemdef.name = "default:stone"; itemdef.name = "default:stone";
itemdef.description = "Stone"; itemdef.description = "Stone";
itemdef.groups["cracky"] = 3;
itemdef.inventory_image = "[inventorycube" itemdef.inventory_image = "[inventorycube"
"{default_stone.png" "{default_stone.png"
"{default_stone.png" "{default_stone.png"
@ -77,11 +78,6 @@ void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *n
for(int i = 0; i < 6; i++) for(int i = 0; i < 6; i++)
f.tname_tiles[i] = "default_stone.png"; f.tname_tiles[i] = "default_stone.png";
f.is_ground_content = true; f.is_ground_content = true;
f.material.diggability = DIGGABLE_NORMAL;
f.material.weight = 5.0;
f.material.crackiness = 1.0;
f.material.crumbliness = -0.1;
f.material.cuttability = -0.2;
idef->registerItem(itemdef); idef->registerItem(itemdef);
ndef->set(i, f); ndef->set(i, f);
@ -93,6 +89,7 @@ void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *n
itemdef.type = ITEM_NODE; itemdef.type = ITEM_NODE;
itemdef.name = "default:dirt_with_grass"; itemdef.name = "default:dirt_with_grass";
itemdef.description = "Dirt with grass"; itemdef.description = "Dirt with grass";
itemdef.groups["crumbly"] = 3;
itemdef.inventory_image = "[inventorycube" itemdef.inventory_image = "[inventorycube"
"{default_grass.png" "{default_grass.png"
"{default_dirt.png&default_grass_side.png" "{default_dirt.png&default_grass_side.png"
@ -104,11 +101,6 @@ void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *n
for(int i = 2; i < 6; i++) for(int i = 2; i < 6; i++)
f.tname_tiles[i] = "default_dirt.png^default_grass_side.png"; f.tname_tiles[i] = "default_dirt.png^default_grass_side.png";
f.is_ground_content = true; f.is_ground_content = true;
f.material.diggability = DIGGABLE_NORMAL;
f.material.weight = 1.2;
f.material.crackiness = 0.0;
f.material.crumbliness = 1.2;
f.material.cuttability = -0.4;
idef->registerItem(itemdef); idef->registerItem(itemdef);
ndef->set(i, f); ndef->set(i, f);
} }

153
src/tool.cpp Normal file

@ -0,0 +1,153 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "tool.h"
#include "utility.h"
#include "itemdef.h" // For itemgroup_get()
#include "log.h"
void ToolCapabilities::serialize(std::ostream &os) const
{
writeU8(os, 0); // version
writeF1000(os, full_punch_interval);
writeS16(os, max_drop_level);
writeU32(os, groupcaps.size());
for(std::map<std::string, ToolGroupCap>::const_iterator
i = groupcaps.begin(); i != groupcaps.end(); i++){
const std::string *name = &i->first;
const ToolGroupCap *cap = &i->second;
os<<serializeString(*name);
writeF1000(os, cap->maxwear);
writeF1000(os, cap->maxlevel);
writeU32(os, cap->times.size());
for(std::map<int, float>::const_iterator
i = cap->times.begin(); i != cap->times.end(); i++){
writeS16(os, i->first);
writeF1000(os, i->second);
}
}
}
void ToolCapabilities::deSerialize(std::istream &is)
{
int version = readU8(is);
if(version != 0) throw SerializationError(
"unsupported ToolCapabilities version");
full_punch_interval = readF1000(is);
max_drop_level = readS16(is);
groupcaps.clear();
u32 groupcaps_size = readU32(is);
for(u32 i=0; i<groupcaps_size; i++){
std::string name = deSerializeString(is);
ToolGroupCap cap;
cap.maxwear = readF1000(is);
cap.maxlevel = readF1000(is);
u32 times_size = readU32(is);
for(u32 i=0; i<times_size; i++){
int level = readS16(is);
float time = readF1000(is);
cap.times[level] = time;
}
groupcaps[name] = cap;
}
}
DigParams getDigParams(const std::map<std::string, int> &groups,
const ToolCapabilities *tp, float time_from_last_punch)
{
//infostream<<"getDigParams"<<std::endl;
/* Check group dig_immediate */
switch(itemgroup_get(groups, "dig_immediate")){
case 1:
//infostream<<"dig_immediate=1"<<std::endl;
return DigParams(true, 0.0, 0);
case 2:
//infostream<<"dig_immediate=2"<<std::endl;
return DigParams(true, 1.0, 0);
default:
break;
}
// Values to be returned (with a bit of conversion)
bool result_diggable = false;
float result_time = 0.0;
float result_wear = 0.0;
int level = itemgroup_get(groups, "level");
//infostream<<"level="<<level<<std::endl;
for(std::map<std::string, ToolGroupCap>::const_iterator
i = tp->groupcaps.begin(); i != tp->groupcaps.end(); i++){
const std::string &name = i->first;
//infostream<<"group="<<name<<std::endl;
const ToolGroupCap &cap = i->second;
int rating = itemgroup_get(groups, name);
float time = 0;
bool time_exists = cap.getTime(rating, &time);
if(!result_diggable || time < result_time){
if(cap.maxlevel > level && time_exists){
result_diggable = true;
result_time = time;
int leveldiff = cap.maxlevel - level;
result_wear = cap.maxwear / pow(4.0, (double)leveldiff);
}
}
}
//infostream<<"result_diggable="<<result_diggable<<std::endl;
//infostream<<"result_time="<<result_time<<std::endl;
//infostream<<"result_wear="<<result_wear<<std::endl;
if(time_from_last_punch < tp->full_punch_interval){
float f = time_from_last_punch / tp->full_punch_interval;
//infostream<<"f="<<f<<std::endl;
result_time /= f;
result_wear /= f;
}
u16 wear_i = 65535.*result_wear;
return DigParams(result_diggable, result_time, wear_i);
}
DigParams getDigParams(const std::map<std::string, int> &groups,
const ToolCapabilities *tp)
{
return getDigParams(groups, tp, 1000000);
}
HitParams getHitParams(const std::map<std::string, int> &groups,
const ToolCapabilities *tp, float time_from_last_punch)
{
DigParams digprop = getDigParams(groups, tp,
time_from_last_punch);
// If digging time would be 1 second, 8 half-hearts go in 1 second.
s16 hp = 0;
if(digprop.diggable)
hp = 8.0 / digprop.time;
// Wear is the same as for digging a single node
s16 wear = (float)digprop.wear;
return HitParams(hp, wear);
}
HitParams getHitParams(const std::map<std::string, int> &groups,
const ToolCapabilities *tp)
{
return getHitParams(groups, tp, 1000000);
}

111
src/tool.h Normal file

@ -0,0 +1,111 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef TOOL_HEADER
#define TOOL_HEADER
#include "common_irrlicht.h"
#include <string>
#include <iostream>
#include <map>
struct ToolGroupCap
{
std::map<int, float> times;
float maxwear;
int maxlevel;
ToolGroupCap():
maxwear(0.05),
maxlevel(1)
{}
bool getTime(int rating, float *time) const
{
std::map<int, float>::const_iterator i = times.find(rating);
if(i == times.end()){
*time = 0;
return false;
}
*time = i->second;
return true;
}
};
struct ToolCapabilities
{
float full_punch_interval;
int max_drop_level;
std::map<std::string, ToolGroupCap> groupcaps;
ToolCapabilities(
float full_punch_interval_=3.0,
int max_drop_level_=1,
std::map<std::string, ToolGroupCap> groupcaps_ =
std::map<std::string, ToolGroupCap>()
):
full_punch_interval(full_punch_interval_),
max_drop_level(max_drop_level_),
groupcaps(groupcaps_)
{}
void serialize(std::ostream &os) const;
void deSerialize(std::istream &is);
};
struct DigParams
{
bool diggable;
// Digging time in seconds
float time;
// Caused wear
u16 wear;
DigParams(bool a_diggable=false, float a_time=0, u16 a_wear=0):
diggable(a_diggable),
time(a_time),
wear(a_wear)
{}
};
DigParams getDigParams(const std::map<std::string, int> &groups,
const ToolCapabilities *tp, float time_from_last_punch);
DigParams getDigParams(const std::map<std::string, int> &groups,
const ToolCapabilities *tp);
struct HitParams
{
s16 hp;
s16 wear;
HitParams(s16 hp_=0, s16 wear_=0):
hp(hp_),
wear(wear_)
{}
};
HitParams getHitParams(const std::map<std::string, int> &groups,
const ToolCapabilities *tp, float time_from_last_punch);
HitParams getHitParams(const std::map<std::string, int> &groups,
const ToolCapabilities *tp);
#endif