From 6a76c226e10e92c3e3339096f07f8ab065e2098b Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 12 Jan 2012 06:10:39 +0100 Subject: The huge item definition and item namespace unification patch (itemdef), see http://c55.me/minetest/wiki/doku.php?id=changes:itemdef --- data/builtin.lua | 589 ++++--- data/clienttextures/unknown_item.png | Bin 0 -> 710 bytes data/mods/bucket/init.lua | 139 +- data/mods/default/init.lua | 1251 +++++++++------ data/mods/experimental/init.lua | 48 +- data/mods/legacy/init.lua | 171 +- src/CMakeLists.txt | 3 +- src/camera.cpp | 211 +-- src/camera.h | 54 +- src/client.cpp | 261 ++-- src/client.h | 29 +- src/clientserver.h | 15 +- src/connection.cpp | 6 +- src/content_cao.cpp | 107 +- src/content_mapblock.cpp | 284 ++-- src/content_mapnode.cpp | 831 +--------- src/content_mapnode.h | 6 - src/content_nodemeta.cpp | 287 ++-- src/content_sao.cpp | 154 +- src/content_sao.h | 8 +- src/craftdef.cpp | 844 ++++++++-- src/craftdef.h | 349 ++++- src/craftitemdef.cpp | 214 --- src/craftitemdef.h | 79 - src/environment.h | 1 + src/game.cpp | 134 +- src/gamedef.h | 10 +- src/guiInventoryMenu.cpp | 149 +- src/guiInventoryMenu.h | 37 +- src/inventory.cpp | 967 +++++------- src/inventory.h | 517 ++---- src/inventorymanager.cpp | 452 ++---- src/inventorymanager.h | 121 +- src/irrlichttypes.h | 2 + src/itemdef.cpp | 502 ++++++ src/itemdef.h | 147 ++ src/mapblock.cpp | 3 + src/mapblock.h | 3 - src/mapblock_mesh.cpp | 76 +- src/mapblock_mesh.h | 8 + src/materials.cpp | 51 +- src/materials.h | 24 +- src/mesh.cpp | 117 ++ src/mesh.h | 22 + src/mineral.cpp | 11 + src/mineral.h | 13 +- src/nodedef.cpp | 199 +-- src/nodedef.h | 49 +- src/player.cpp | 10 +- src/player.h | 14 +- src/scriptapi.cpp | 2859 +++++++++++++++++----------------- src/scriptapi.h | 21 +- src/server.cpp | 976 +++++------- src/server.h | 28 +- src/serverobject.cpp | 29 +- src/serverobject.h | 27 +- src/serverremoteplayer.cpp | 155 +- src/serverremoteplayer.h | 20 +- src/test.cpp | 198 ++- src/tile.cpp | 190 +-- src/tile.h | 4 + src/tooldef.cpp | 238 --- src/tooldef.h | 103 -- src/utility.cpp | 95 ++ src/utility.h | 6 + 65 files changed, 7239 insertions(+), 7289 deletions(-) create mode 100644 data/clienttextures/unknown_item.png delete mode 100644 src/craftitemdef.cpp delete mode 100644 src/craftitemdef.h create mode 100644 src/itemdef.cpp create mode 100644 src/itemdef.h delete mode 100644 src/tooldef.cpp delete mode 100644 src/tooldef.h diff --git a/data/builtin.lua b/data/builtin.lua index 1046e934e..1926d88b4 100644 --- a/data/builtin.lua +++ b/data/builtin.lua @@ -80,15 +80,91 @@ function dump(o, dumped) end -- --- Built-in node definitions. Also defined in C. +-- Item definition helpers +-- + +minetest.inventorycube = function(img1, img2, img3) + img2 = img2 or img1 + img3 = img3 or img1 + return "[inventorycube" + .. "{" .. img1:gsub("%^", "&") + .. "{" .. img2:gsub("%^", "&") + .. "{" .. img3:gsub("%^", "&") +end + +minetest.get_pointed_thing_position = function(pointed_thing, above) + if pointed_thing.type == "node" then + if above then + -- The position where a node would be placed + return pointed_thing.above + else + -- The position where a node would be dug + return pointed_thing.under + end + elseif pointed_thing.type == "object" then + obj = pointed.thing.ref + if obj ~= nil then + return obj:getpos() + else + return nil + end + else + return nil + end +end + +function minetest.item_place(itemstack, placer, pointed_thing) + pos = minetest.get_pointed_thing_position(pointed_thing, true) + if pos ~= nil then + item = itemstack:take_item() + if item ~= nil then + minetest.env:add_item(pos, item) + end + end + return itemstack +end + +function minetest.item_drop(itemstack, dropper, pos) + minetest.env:add_item(pos, itemstack) + return "" +end + +function minetest.item_eat(hp_change) + return function(itemstack, user, pointed_thing) -- closure + if itemstack:take_item() ~= nil then + user:set_hp(user:get_hp() + hp_change) + end + return itemstack + end +end + +-- +-- Item definition defaults -- -minetest.register_nodedef_defaults({ +minetest.nodedef_default = { + -- Item properties + type="node", -- name intentionally not defined here + description = "", + inventory_image = "", + wield_image = "", + wield_scale = {x=1,y=1,z=1}, + stack_max = 99, + dropcount = -1, + usable = false, + liquids_pointable = false, + tool_digging_properties = nil, + + -- Interaction callbacks + on_place = nil, -- let C handle node placement for now + on_drop = minetest.item_drop, + on_use = nil, + + -- Node properties drawtype = "normal", visual_scale = 1.0, - tile_images = {"unknown_block.png"}, - inventory_image = "unknown_block.png", + tile_images = {""}, special_materials = { {image="", backface_culling=true}, {image="", backface_culling=true}, @@ -104,8 +180,7 @@ minetest.register_nodedef_defaults({ climbable = false, buildable_to = false, wall_mounted = false, - often_contains_mineral = false, - dug_item = "", + --dug_item intentionally not defined here extra_dug_item = "", extra_dug_item_rarity = 2, metadata_name = "", @@ -124,219 +199,349 @@ minetest.register_nodedef_defaults({ cuttability = 0, flammability = 0, }, - cookresult_item = "", -- Cannot be cooked - furnace_cooktime = 3.0, - furnace_burntime = -1, -- Cannot be used as fuel -}) +} -minetest.register_node("air", { - drawtype = "airlike", - paramtype = "light", - sunlight_propagates = true, - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, - air_equivalent = true, -}) +minetest.craftitemdef_default = { + type="craft", + -- name intentionally not defined here + description = "", + inventory_image = "", + wield_image = "", + wield_scale = {x=1,y=1,z=1}, + stack_max = 99, + liquids_pointable = false, + tool_digging_properties = nil, + + -- Interaction callbacks + on_place = minetest.item_place, + on_drop = minetest.item_drop, + on_use = nil, +} + +minetest.tooldef_default = { + type="tool", + -- name intentionally not defined here + description = "", + inventory_image = "", + wield_image = "", + wield_scale = {x=1,y=1,z=1}, + stack_max = 1, + liquids_pointable = false, + tool_digging_properties = nil, + + -- Interaction callbacks + on_place = minetest.item_place, + on_drop = minetest.item_drop, + on_use = nil, +} + +minetest.noneitemdef_default = { -- This is used for the hand and unknown items + type="none", + -- name intentionally not defined here + description = "", + inventory_image = "", + wield_image = "", + wield_scale = {x=1,y=1,z=1}, + stack_max = 99, + liquids_pointable = false, + tool_digging_properties = nil, + + -- Interaction callbacks + on_place = nil, + on_drop = nil, + on_use = nil, +} -minetest.register_node("ignore", { - drawtype = "airlike", - paramtype = "none", - sunlight_propagates = false, - walkable = false, - pointable = false, - diggable = false, - buildable_to = true, -- A way to remove accidentally placed ignores - air_equivalent = true, -}) +-- +-- Make raw registration functions inaccessible to anyone except builtin.lua +-- + +local register_item_raw = minetest.register_item_raw +minetest.register_item_raw = nil + +local register_alias_raw = minetest.register_alias_raw +minetest.register_item_raw = nil -- --- stackstring manipulation functions --- example stackstring: 'craft "apple" 4' --- example item: {type="craft", name="apple"} --- example item: {type="tool", name="SteelPick", wear="23272"} +-- Item / entity / ABM registration functions -- -function stackstring_take_item(stackstring) - if stackstring == nil then - return '', nil - end - local stacktype = nil - stacktype = string.match(stackstring, - '([%a%d]+)') - if stacktype == "node" or stacktype == "craft" then - local itemtype = nil - local itemname = nil - local itemcount = nil - itemtype, itemname, itemcount = string.match(stackstring, - '([%a%d]+) "([^"]*)" (%d+)') - itemcount = tonumber(itemcount) - if itemcount == 0 then - return '', nil - elseif itemcount == 1 then - return '', {type=itemtype, name=itemname} - else - return itemtype.." \""..itemname.."\" "..(itemcount-1), - {type=itemtype, name=itemname} +minetest.registered_abms = {} +minetest.registered_entities = {} +minetest.registered_items = {} +minetest.registered_nodes = {} +minetest.registered_craftitems = {} +minetest.registered_tools = {} +minetest.registered_aliases = {} + +-- For tables that are indexed by item name: +-- If table[X] does not exist, default to table[minetest.registered_aliases[X]] +local function set_alias_metatable(table) + setmetatable(table, { + __index = function(name) + return rawget(table, minetest.registered_aliases[name]) + end + }) +end +set_alias_metatable(minetest.registered_items) +set_alias_metatable(minetest.registered_nodes) +set_alias_metatable(minetest.registered_craftitems) +set_alias_metatable(minetest.registered_tools) + +-- These item names may not be used because they would interfere +-- with legacy itemstrings +local forbidden_item_names = { + MaterialItem = true, + MaterialItem2 = true, + MaterialItem3 = true, + NodeItem = true, + node = true, + CraftItem = true, + craft = true, + MBOItem = true, + ToolItem = true, + tool = true, +} + +local function check_modname_prefix(name) + if name:sub(1,1) == ":" then + -- Escape the modname prefix enforcement mechanism + return name:sub(2) + else + -- Modname prefix enforcement + local expected_prefix = minetest.get_current_modname() .. ":" + if name:sub(1, #expected_prefix) ~= expected_prefix then + error("Name " .. name .. " does not follow naming conventions: " .. + "\"modname:\" or \":\" prefix required") end - elseif stacktype == "tool" then - local itemtype = nil - local itemname = nil - local itemwear = nil - itemtype, itemname, itemwear = string.match(stackstring, - '([%a%d]+) "([^"]*)" (%d+)') - itemwear = tonumber(itemwear) - return '', {type=itemtype, name=itemname, wear=itemwear} + local subname = name:sub(#expected_prefix+1) + if subname:find("[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]") then + error("Name " .. name .. " does not follow naming conventions: " .. + "contains unallowed characters") + end + return name end end -function stackstring_put_item(stackstring, item) - if item == nil then - return stackstring, false +function minetest.register_abm(spec) + -- Add to minetest.registered_abms + minetest.registered_abms[#minetest.registered_abms+1] = spec +end + +function minetest.register_entity(name, prototype) + -- Check name + if name == nil then + error("Unable to register entity: Name is nil") end - stackstring = stackstring or '' - local stacktype = nil - stacktype = string.match(stackstring, - '([%a%d]+)') - stacktype = stacktype or '' - if stacktype ~= '' and stacktype ~= item.type then - return stackstring, false + name = check_modname_prefix(tostring(name)) + + prototype.name = name + prototype.__index = prototype -- so that it can be used as a metatable + + -- Add to minetest.registered_entities + minetest.registered_entities[name] = prototype +end + +function minetest.register_item(name, itemdef) + -- Check name + if name == nil then + error("Unable to register item: Name is nil") end - if item.type == "node" or item.type == "craft" then - local itemtype = nil - local itemname = nil - local itemcount = nil - itemtype, itemname, itemcount = string.match(stackstring, - '([%a%d]+) "([^"]*)" (%d+)') - itemtype = itemtype or item.type - itemname = itemname or item.name - if itemcount == nil then - itemcount = 0 - end - itemcount = itemcount + 1 - return itemtype.." \""..itemname.."\" "..itemcount, true - elseif item.type == "tool" then - if stacktype ~= nil then - return stackstring, false - end - local itemtype = nil - local itemname = nil - local itemwear = nil - itemtype, itemname, itemwear = string.match(stackstring, - '([%a%d]+) "([^"]*)" (%d+)') - itemwear = tonumber(itemwear) - return itemtype.." \""..itemname.."\" "..itemwear, true + name = check_modname_prefix(tostring(name)) + if forbidden_item_names[name] then + error("Unable to register item: Name is forbidden: " .. name) + end + itemdef.name = name + + -- Apply defaults and add to registered_* table + if itemdef.type == "node" then + setmetatable(itemdef, {__index = minetest.nodedef_default}) + minetest.registered_nodes[itemdef.name] = itemdef + elseif itemdef.type == "craft" then + setmetatable(itemdef, {__index = minetest.craftitemdef_default}) + minetest.registered_craftitems[itemdef.name] = itemdef + elseif itemdef.type == "tool" then + setmetatable(itemdef, {__index = minetest.tooldef_default}) + minetest.registered_tools[itemdef.name] = itemdef + elseif itemdef.type == "none" then + setmetatable(itemdef, {__index = minetest.noneitemdef_default}) + else + error("Unable to register item: Type is invalid: " .. dump(itemdef)) end - return stackstring, false -end -function stackstring_put_stackstring(stackstring, src) - while src ~= '' do - --print("src="..dump(src)) - src, item = stackstring_take_item(src) - --print("src="..dump(src).." item="..dump(item)) - local success - stackstring, success = stackstring_put_item(stackstring, item) - if not success then - return stackstring, false - end + -- Default dug item + if itemdef.type == "node" and itemdef.dug_item == nil then + itemdef.dug_item = ItemStack({name=itemdef.name}):to_string() end - return stackstring, true + + -- Legacy stuff + if itemdef.cookresult_itemstring ~= nil and itemdef.cookresult_itemstring ~= "" then + minetest.register_craft({ + type="cooking", + output=itemdef.cookresult_itemstring, + recipe=itemdef.name, + cooktime=itemdef.furnace_cooktime + }) + end + if itemdef.furnace_burntime ~= nil and itemdef.furnace_burntime >= 0 then + minetest.register_craft({ + type="fuel", + recipe=itemdef.name, + burntime=itemdef.furnace_burntime + }) + end + + -- Disable all further modifications + getmetatable(itemdef).__newindex = {} + + --minetest.log("Registering item: " .. itemdef.name) + minetest.registered_items[itemdef.name] = itemdef + minetest.registered_aliases[itemdef.name] = nil + register_item_raw(itemdef) end -function test_stackstring() - local stack - local item - local success - - stack, item = stackstring_take_item('node "TNT" 3') - assert(stack == 'node "TNT" 2') - assert(item.type == 'node') - assert(item.name == 'TNT') - - stack, item = stackstring_take_item('craft "with spaces" 2') - assert(stack == 'craft "with spaces" 1') - assert(item.type == 'craft') - assert(item.name == 'with spaces') - - stack, item = stackstring_take_item('craft "with spaces" 1') - assert(stack == '') - assert(item.type == 'craft') - assert(item.name == 'with spaces') - - stack, item = stackstring_take_item('craft "s8df2kj3" 0') - assert(stack == '') - assert(item == nil) - - stack, item = stackstring_take_item('tool "With Spaces" 32487') - assert(stack == '') - assert(item.type == 'tool') - assert(item.name == 'With Spaces') - assert(item.wear == 32487) - - stack, success = stackstring_put_item('node "With Spaces" 40', - {type='node', name='With Spaces'}) - assert(stack == 'node "With Spaces" 41') - assert(success == true) - - stack, success = stackstring_put_item('craft "With Spaces" 40', - {type='craft', name='With Spaces'}) - assert(stack == 'craft "With Spaces" 41') - assert(success == true) - - stack, success = stackstring_put_item('tool "With Spaces" 32487', - {type='tool', name='With Spaces'}) - assert(stack == 'tool "With Spaces" 32487') - assert(success == false) - - stack, success = stackstring_put_item('node "With Spaces" 40', - {type='tool', name='With Spaces'}) - assert(stack == 'node "With Spaces" 40') - assert(success == false) - - assert(stackstring_put_stackstring('node "With Spaces" 2', - 'node "With Spaces" 1') == 'node "With Spaces" 3') +function minetest.register_node(name, nodedef) + nodedef.type = "node" + minetest.register_item(name, nodedef) end -test_stackstring() --- --- NodeItem helpers --- +function minetest.register_craftitem(name, craftitemdef) + craftitemdef.type = "craft" -minetest.inventorycube = function(img1, img2, img3) - img2 = img2 or img1 - img3 = img3 or img1 - return "[inventorycube" - .. "{" .. img1:gsub("%^", "&") - .. "{" .. img2:gsub("%^", "&") - .. "{" .. img3:gsub("%^", "&") + -- Legacy stuff + if craftitemdef.inventory_image == nil and craftitemdef.image ~= nil then + craftitemdef.inventory_image = craftitemdef.image + end + + minetest.register_item(name, craftitemdef) end --- --- CraftItem helpers --- +function minetest.register_tool(name, tooldef) + tooldef.type = "tool" + tooldef.stack_max = 1 + + -- Legacy stuff + if tooldef.inventory_image == nil and tooldef.image ~= nil then + tooldef.inventory_image = tooldef.image + end + if tooldef.tool_digging_properties == nil and + (tooldef.full_punch_interval ~= nil or + tooldef.basetime ~= nil or + tooldef.dt_weight ~= nil or + tooldef.dt_crackiness ~= nil or + tooldef.dt_crumbliness ~= nil or + tooldef.dt_cuttability ~= nil or + tooldef.basedurability ~= nil or + tooldef.dd_weight ~= nil or + tooldef.dd_crackiness ~= nil or + tooldef.dd_crumbliness ~= nil or + tooldef.dd_cuttability ~= nil) then + tooldef.tool_digging_properties = { + full_punch_interval = tooldef.full_punch_interval, + basetime = tooldef.basetime, + dt_weight = tooldef.dt_weight, + dt_crackiness = tooldef.dt_crackiness, + dt_crumbliness = tooldef.dt_crumbliness, + dt_cuttability = tooldef.dt_cuttability, + basedurability = tooldef.basedurability, + dd_weight = tooldef.dd_weight, + dd_crackiness = tooldef.dd_crackiness, + dd_crumbliness = tooldef.dd_crumbliness, + dd_cuttability = tooldef.dd_cuttability, + } + end -minetest.craftitem_place_item = function(item, placer, pos) - --print("craftitem_place_item") - --print("item: " .. dump(item)) - --print("placer: " .. dump(placer)) - --print("pos: " .. dump(pos)) - minetest.env:add_item(pos, 'craft "' .. item .. '" 1') - return true + minetest.register_item(name, tooldef) end -minetest.craftitem_eat = function(hp_change) - return function(item, user, pointed_thing) -- closure - --print("craftitem_eat(" .. hp_change .. ")") - --print("item: " .. dump(item)) - --print("user: " .. dump(user)) - --print("pointed_thing: " .. dump(pointed_thing)) - user:set_hp(user:get_hp() + hp_change) - return true +function minetest.register_alias(name, convert_to) + if forbidden_item_names[name] then + error("Unable to register alias: Name is forbidden: " .. name) end + if minetest.registered_items[name] ~= nil then + minetest.log("WARNING: Not registering alias, item with same name" .. + " is already defined: " .. name .. " -> " .. convert_to) + else + --minetest.log("Registering alias: " .. name .. " -> " .. convert_to) + minetest.registered_aliases[name] = convert_to + register_alias_raw(name, convert_to) + end +end + +-- Alias the forbidden item names to "" so they can't be +-- created via itemstrings (e.g. /give) +local name +for name in pairs(forbidden_item_names) do + minetest.registered_aliases[name] = "" + register_alias_raw(name, "") end + +-- Deprecated: +-- Aliases for minetest.register_alias (how ironic...) +--minetest.alias_node = minetest.register_alias +--minetest.alias_tool = minetest.register_alias +--minetest.alias_craftitem = minetest.register_alias + +-- +-- Built-in node definitions. Also defined in C. +-- + +minetest.register_item(":", { + type = "none", + wield_image = "wieldhand.png", + wield_scale = {x=1,y=1,z=2.5}, + tool_digging_properties = { + full_punch_interval = 2.0, + basetime = 0.5, + dt_weight = 1, + dt_crackiness = 0, + dt_crumbliness = -1, + dt_cuttability = 0, + basedurability = 50, + dd_weight = 0, + dd_crackiness = 0, + dd_crumbliness = 0, + dd_cuttability = 0, + } +}) + +minetest.register_item(":unknown", { + type = "none", + description = "Unknown Item", + inventory_image = "unknown_item.png", + on_place = minetest.item_place, + on_drop = minetest.item_drop, +}) + +minetest.register_node(":air", { + description = "Air (you hacker you!)", + inventory_image = "unknown_block.png", + wield_image = "unknown_block.png", + drawtype = "airlike", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + air_equivalent = true, +}) + +minetest.register_node(":ignore", { + description = "Ignore (you hacker you!)", + inventory_image = "unknown_block.png", + wield_image = "unknown_block.png", + drawtype = "airlike", + paramtype = "none", + sunlight_propagates = false, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, -- A way to remove accidentally placed ignores + air_equivalent = true, +}) + -- -- Default material types -- @@ -422,7 +627,7 @@ end -- Callback registration -- -function make_registration() +local function make_registration() local t = {} local registerfunc = function(func) table.insert(t, func) end return t, registerfunc diff --git a/data/clienttextures/unknown_item.png b/data/clienttextures/unknown_item.png new file mode 100644 index 000000000..35cabf0ad Binary files /dev/null and b/data/clienttextures/unknown_item.png differ diff --git a/data/mods/bucket/init.lua b/data/mods/bucket/init.lua index 639a614d4..8ed9da522 100644 --- a/data/mods/bucket/init.lua +++ b/data/mods/bucket/init.lua @@ -1,80 +1,95 @@ -- bucket (Minetest 0.4 mod) -- A bucket, which can pick up water and lava -minetest.alias_craftitem("bucket", "bucket:bucket_empty") -minetest.alias_craftitem("bucket_water", "bucket:bucket_water") -minetest.alias_craftitem("bucket_lava", "bucket:bucket_lava") +minetest.register_alias("bucket", "bucket:bucket_empty") +minetest.register_alias("bucket_water", "bucket:bucket_water") +minetest.register_alias("bucket_lava", "bucket:bucket_lava") minetest.register_craft({ - output = 'craft "bucket:bucket_empty" 1', + output = 'bucket:bucket_empty 1', recipe = { - {'craft "steel_ingot"', '', 'craft "steel_ingot"'}, - {'', 'craft "steel_ingot"', ''}, + {'default:steel_ingot', '', 'default:steel_ingot'}, + {'', 'default:steel_ingot', ''}, } }) -minetest.register_craftitem("bucket:bucket_empty", { - image = "bucket.png", - stack_max = 1, - liquids_pointable = true, - on_place_on_ground = minetest.craftitem_place_item, - on_use = function(item, player, pointed_thing) - if pointed_thing.type == "node" then - n = minetest.env:get_node(pointed_thing.under) - if n.name == "default:water_source" then - minetest.env:add_node(pointed_thing.under, {name="air"}) - player:add_to_inventory_later('craft "bucket:bucket_water" 1') - return true - elseif n.name == "default:lava_source" then - minetest.env:add_node(pointed_thing.under, {name="air"}) - player:add_to_inventory_later('craft "bucket:bucket_lava" 1') - return true +bucket = {} +bucket.liquids = {} + +-- Register a new liquid +-- source = name of the source node +-- flowing = name of the flowing node +-- itemname = name of the new bucket item (or nil if liquid is not takeable) +-- inventory_image = texture of the new bucket item (ignored if itemname == nil) +-- This function can be called from any mod (that depends on bucket). +function bucket.register_liquid(source, flowing, itemname, inventory_image) + bucket.liquids[source] = { + source = source, + flowing = flowing, + itemname = itemname, + } + bucket.liquids[flowing] = bucket.liquids[source] + + if itemname ~= nil then + minetest.register_craftitem(itemname, { + inventory_image = inventory_image, + stack_max = 1, + liquids_pointable = true, + on_use = function(itemstack, user, pointed_thing) + -- Must be pointing to node + if pointed_thing.type ~= "node" then + return + end + -- Check if pointing to a liquid + n = minetest.env:get_node(pointed_thing.under) + if bucket.liquids[n.name] == nil then + -- Not a liquid + minetest.env:add_node(pointed_thing.above, {name=source}) + elseif n.name ~= source then + -- It's a liquid + minetest.env:add_node(pointed_thing.under, {name=source}) + end + return {name="bucket:bucket_empty"} end - end - return false - end, -}) + }) + end +end -minetest.register_craftitem("bucket:bucket_water", { - image = "bucket_water.png", +minetest.register_craftitem("bucket:bucket_empty", { + inventory_image = "bucket.png", stack_max = 1, liquids_pointable = true, - on_place_on_ground = minetest.craftitem_place_item, - on_use = function(item, player, pointed_thing) - if pointed_thing.type == "node" then - n = minetest.env:get_node(pointed_thing.under) - if n.name == "default:water_source" then - -- unchanged - elseif n.name == "default:water_flowing" or n.name == "default:lava_source" or n.name == "default:lava_flowing" then - minetest.env:add_node(pointed_thing.under, {name="default:water_source"}) - else - minetest.env:add_node(pointed_thing.above, {name="default:water_source"}) - end - player:add_to_inventory_later('craft "bucket:bucket_empty" 1') - return true + on_use = function(itemstack, user, pointed_thing) + -- Must be pointing to node + if pointed_thing.type ~= "node" then + return + end + -- Check if pointing to a liquid source + n = minetest.env:get_node(pointed_thing.under) + liquiddef = bucket.liquids[n.name] + if liquiddef ~= nil and liquiddef.source == n.name and liquiddef.itemname ~= nil then + minetest.env:add_node(pointed_thing.under, {name="air"}) + return {name=liquiddef.itemname} end - return false end, }) -minetest.register_craftitem("bucket:bucket_lava", { - image = "bucket_lava.png", - stack_max = 1, - liquids_pointable = true, - on_place_on_ground = minetest.craftitem_place_item, - on_use = function(item, player, pointed_thing) - if pointed_thing.type == "node" then - n = minetest.env:get_node(pointed_thing.under) - if n.name == "default:lava_source" then - -- unchanged - elseif n.name == "default:water_source" or n.name == "default:water_flowing" or n.name == "default:lava_flowing" then - minetest.env:add_node(pointed_thing.under, {name="default:lava_source"}) - else - minetest.env:add_node(pointed_thing.above, {name="default:lava_source"}) - end - player:add_to_inventory_later('craft "bucket:bucket_empty" 1') - return true - end - return false - end, +bucket.register_liquid( + "default:water_source", + "default:water_flowing", + "bucket:bucket_water", + "bucket_water.png" +) + +bucket.register_liquid( + "default:lava_source", + "default:lava_flowing", + "bucket:bucket_lava", + "bucket_lava.png" +) + +minetest.register_craft({ + type = "fuel", + recipe = "default:bucket_lava", + burntime = 60, }) diff --git a/data/mods/default/init.lua b/data/mods/default/init.lua index aa03eabe8..2bd950230 100644 --- a/data/mods/default/init.lua +++ b/data/mods/default/init.lua @@ -77,24 +77,25 @@ -- eg. 'tool "default:pick_wood" 21323' -- eg. 'craft "default:apple" 2' -- --- item: A single item in Lua table format. --- eg. {type="node", name="default:dirt"} +-- item: A stack of items in Lua table format. +-- eg. {name="default:dirt", count=1, wear=0, metadata=""} -- ^ a single dirt node --- eg. {type="tool", name="default:pick_wood", wear=21323} +-- eg. {name="default:pick_wood", count=1, wear=21323, metadata=""} -- ^ a wooden pick about 1/3 weared out --- eg. {type="craft", name="default:apple"} +-- eg. {name="default:apple", count=1, wear=0, metadata=""} -- ^ an apple. -- +-- Any time an item must be passed to a function, it can be an +-- ItemStack (see below), an itemstring or a table in the above format. +-- -- Global functions: -- minetest.register_entity(name, prototype table) --- minetest.register_tool(name, tool definition) +-- minetest.register_abm(abm definition) -- minetest.register_node(name, node definition) --- minetest.register_craftitem(name, craftitem definition) +-- minetest.register_tool(name, item definition) +-- minetest.register_craftitem(name, item definition) +-- minetest.register_alias(name, convert_to) -- minetest.register_craft(recipe) --- minetest.register_abm(abm definition) --- minetest.alias_node(name, convert_to) --- minetest.alias_tool(name, convert_to) --- minetest.alias_craftitem(name, convert_to) -- minetest.register_globalstep(func(dtime)) -- minetest.register_on_placenode(func(pos, newnode, placer)) -- minetest.register_on_dignode(func(pos, oldnode, digger)) @@ -113,13 +114,16 @@ -- minetest.chat_send_player(name, text) -- minetest.get_player_privs(name) -> set of privs -- minetest.get_inventory(location) -> InvRef +-- minetest.get_current_modname() -> string -- minetest.get_modpath(modname) -> eg. "/home/user/.minetest/usermods/modname" -- ^ location = eg. {type="player", name="celeron55"} -- {type="node", pos={x=, y=, z=}} -- --- stackstring_take_item(stackstring) -> stackstring, item --- stackstring_put_item(stackstring, item) -> stackstring, success --- stackstring_put_stackstring(stackstring, stackstring) -> stackstring, success +-- minetest.debug(line) +-- ^ Goes to dstream +-- minetest.log(line) +-- minetest.log(loglevel, line) +-- ^ loglevel one of "error", "action", "info", "verbose" -- -- minetest.digprop_constanttime(time) -- minetest.digprop_stonelike(toughness) @@ -133,10 +137,14 @@ -- minetest.env - environment reference -- -- Global tables: +-- minetest.registered_items +-- ^ List of registered items, indexed by name -- minetest.registered_nodes -- ^ List of registered node definitions, indexed by name -- minetest.registered_craftitems -- ^ List of registered craft item definitions, indexed by name +-- minetest.registered_tools +-- ^ List of registered tool definitions, indexed by name -- minetest.registered_entities -- ^ List of registered entity prototypes, indexed by name -- minetest.object_refs @@ -171,8 +179,6 @@ -- Generic node metadata specific: -- - set_infotext(infotext) -- - get_inventory() -> InvRef --- - inventory_set_list(name, {item1, item2, ...}) --- - inventory_get_list(name) -- - set_inventory_draw_spec(string) -- - set_allow_text_input(bool) -- - set_allow_removal(bool) @@ -194,12 +200,13 @@ -- ^ puncher = an another ObjectRef, -- ^ time_from_last_punch = time since last punch action of the puncher -- - right_click(clicker); clicker = an another ObjectRef --- - get_wield_digging_properties() -> digging property table --- - damage_wielded_item(num) (item damage/wear range is 0-65535) --- - add_to_inventory(itemstring): add an item to object inventory (actually only works for the player as of now) --- - add_to_inventory_later(itemstring): like above, but after callback returns (only allowed for craftitem callbacks) -- - get_hp(): returns number of hitpoints (2 * number of hearts) -- - set_hp(hp): set number of hitpoints (2 * number of hearts) +-- - get_inventory() -> InvRef +-- - get_wield_list(): returns the name of the inventory list the wielded item is in +-- - get_wield_index(): returns the index of the wielded item +-- - get_wielded_item() -> ItemStack +-- - set_wielded_item(item): replaces the wielded item, returns true if successful -- LuaEntitySAO-only: (no-op for other objects) -- - setvelocity({x=num, y=num, z=num}) -- - getvelocity() -> {x=num, y=num, z=num} @@ -216,9 +223,6 @@ -- - get_luaentity() -- Player-only: (no-op for other objects) -- - get_player_name(): will return nil if is not a player --- - get_inventory() -> InvRef --- - inventory_set_list(name, {item1, item2, ...}) --- - inventory_get_list(name) -> {item1, item2, ...} -- - get_look_dir(): get camera direction as a unit vector -- - get_look_pitch(): pitch in radians -- - get_look_yaw(): yaw in radians (wraps around pretty randomly as of now) @@ -230,14 +234,41 @@ -- - set_stack(listname, i, stack): copy stack to index i in list -- - get_list(listname): return full list -- - set_list(listname, list): set full list (size will not change) --- - autoinsert_stack(listname, stack): insert stack somewhere in list --- - autoinsert_stackstring(listname, stackstring) +-- - add_item(listname, stack): add item somewhere in list, returns leftover ItemStack +-- - room_for_item(listname, stack): returns true if the stack of items +-- can be fully added to the list +-- - contains_item(listname, stack): returns true if the stack of items +-- can be fully taken from the list +-- remove_item(listname, stack): take as many items as specified from the list, +-- returns the items that were actually removed (as an ItemStack) -- -- ItemStack methods: --- - peek_item(): return item from stack without removing it --- - take_item(): remove item from stack and return it --- - put_item(item): put item in stack; return false if not possible --- - put_stackstring(stackstring): return false if not possible +-- - is_empty(): return true if stack is empty +-- - get_name(): returns item name (e.g. "default:stone") +-- - get_count(): returns number of items on the stack +-- - get_wear(): returns tool wear (0-65535), 0 for non-tools +-- - get_metadata(): returns metadata (a string attached to an item stack) +-- - clear(): removes all items from the stack, making it empty +-- - replace(item): replace the contents of this stack (item can also +-- be an itemstring or table) +-- - to_string(): returns the stack in itemstring form +-- - to_table(): returns the stack in Lua table form +-- - get_stack_max(): returns the maximum size of the stack (depends on the item) +-- - get_free_space(): returns get_stack_max() - get_count() +-- - is_known(): returns true if the item name refers to a defined item type +-- - get_definition(): returns the item definition table +-- - get_tool_digging_properties(): returns the digging properties of the item, +-- ^ 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_item(item): put some item or stack onto this stack, +-- ^ returns leftover ItemStack +-- - item_fits(item): returns true if item or stack can be fully added to this one +-- - take_item(n): take (and remove) up to n items from this stack +-- ^ returns taken ItemStack +-- ^ if n is omitted, n=1 is used +-- - peek_item(n): copy (don't remove) up to n items from this stack +-- ^ returns copied ItemStack +-- ^ if n is omitted, n=1 is used -- -- Registered entities: -- - Functions receive a "luaentity" as self: @@ -271,29 +302,38 @@ -- myvariable = whatever, -- } -- --- Tool definition: +-- Item definition: -- { --- image = "default_tool_steelaxe.png", --- full_punch_interval = 1.0, --- basetime = 1.0, --- dt_weight = 0.5, --- dt_crackiness = -0.2, --- dt_crumbliness = 1, --- dt_cuttability = -0.5, --- basedurability = 330, --- dd_weight = 0, --- dd_crackiness = 0, --- dd_crumbliness = 0, --- dd_cuttability = 0, +-- description = "Steel Axe", +-- inventory_image = "default_tool_steelaxe.png", +-- wield_image = "", +-- wield_scale = {x=1,y=1,z=1}, +-- stack_max = 99, +-- liquids_pointable = false, +-- tool_digging_properties = { +-- full_punch_interval = 1.0, +-- basetime = 1.0, +-- dt_weight = 0.5, +-- dt_crackiness = -0.2, +-- dt_crumbliness = 1, +-- dt_cuttability = -0.5, +-- basedurability = 330, +-- dd_weight = 0, +-- dd_crackiness = 0, +-- dd_crumbliness = 0, +-- dd_cuttability = 0, +-- } +-- on_drop = func(item, dropper, pos), +-- on_place = func(item, placer, pointed_thing), +-- on_use = func(item, user, pointed_thing), -- } -- -- Node definition options: -- { --- name = "modname:somenode", +-- , -- drawtype = "normal", -- visual_scale = 1.0, -- tile_images = {"default_unknown_block.png"}, --- inventory_image = "default_unknown_block.png", -- special_materials = { -- {image="", backface_culling=true}, -- {image="", backface_culling=true}, @@ -309,7 +349,6 @@ -- climbable = false, -- buildable_to = false, -- wall_mounted = false, --- often_contains_mineral = false, -- dug_item = "", -- extra_dug_item = "", -- extra_dug_item_rarity = 2, @@ -329,34 +368,67 @@ -- cuttability = 0, -- flammability = 0, -- }, --- cookresult_itemstring = "", -- Cannot be cooked --- furnace_cooktime = 3.0, --- furnace_burntime = -1, -- Cannot be used as fuel +-- on_drop = func(item, dropper), +-- on_place = func(item, placer, pointed_thing), +-- on_use = func(item, user, pointed_thing), -- } -- -- Craftitem definition options: --- minetest.register_craftitem("modname_name", { --- image = "default_image.png", +-- { +-- description = , +-- inventory_image = "default_unknown_block.png", +-- wield_image = "", -- stack_max = , --- cookresult_itemstring = itemstring (result of cooking), --- furnace_cooktime = , --- furnace_burntime =