Modding Minetest - Node Breaker
One of the most important blocks in every automation machine built inside minetest is the node breaker. It is a very expensive block to craft but it can harvest resources from the environment as if you were there.
It’s most basic use is to harvest wheat or stone in an endless cycle of repetitive work that no one is interested doing.
So how do we replicate some of it’s features?
minetest.register_node("awittymodname:nodebreaker", {
description = "Node breaker",
on_punch = function(pos, node, player, pointed_thing)
-- do something amazing here
end,
})
This is how we register a node called nodebreaker
in the mod named awittymodname
.
I added only two fields to the node properties and the interesting one is on_punch
.
Obvioulsy when we will punch the node nothing will happen because there is no meaningful code inside the function, that’s just a seed to get going.
Let’s make it destroy some node.
minetest.register_node("awittymodname:nodebreaker", {
description = "Node breaker",
on_punch = function(pos, node, player, pointed_thing)
-- there are 6 possible directions
-- one for every face of the cube
-- this will return the exiting vector
-- associated with the face 0
local direction = minetest.facedir_to_dir(0)
-- add the direction vector to
-- the node position to get the target
local target_position = vector.add(pos, dir)
-- dig the node as if a player did
minetest.dig_node(target_position)
end,
})
This implementation uses the facedir to dir and vector API
So now every time we punch the node breaker the node facing the face 0 will be destroyed.
But that wont drop resources, dammit!
minetest.register_node("awittymodname:nodebreaker", {
description = "Node breaker",
on_punch = function(pos, node, player, pointed_thing)
-- there are 6 possible directions
-- one for every face of the cube
-- this will return the exiting vector
-- associated with the face 0
local direction = minetest.facedir_to_dir(0)
-- add the direction vector to
-- the node position to get the target
local target_position = vector.add(pos, direction)
-- get the node in target_position
-- return nil if it does not exists
local target_node = minetest.get_node_or_nil(target_position)
-- if there is a node in target position
if target_node then
-- get a list of item names
-- the target node would drop
-- if digged by a player with bare hands
local target_node_drop = minetest.get_node_drops(target_node.name, nil)
-- for every item the node would drop
-- add it to the game in the target node position
for _, dropname in ipairs(target_node_drop) do
minetest.add_item(target_position, dropname)
end
-- and finally
-- dig the node as if a player did
minetest.dig_node(target_position)
end
end,
})
By using the get node drops API we can obtain the list of item names that the node will drop if digged and by using the add item API we add the items to the world.
So now our node breaker can dig blocks as if a player would, by dropping the resources in the world.
This is very good but still requires to punch the node to dig it, maybe it’s time to think about timers…
Key points
We can create nodes to fit our needs.
It is very simple to emulate the work of a player.