Item Callbacks: Add chapter
This commit is contained in:
parent
bc8820c4b6
commit
f8c9da8261
207
_en/items/callbacks.md
Normal file
207
_en/items/callbacks.md
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
---
|
||||||
|
title: Node and Item Callbacks
|
||||||
|
layout: default
|
||||||
|
root: ../..
|
||||||
|
idx: 2.15
|
||||||
|
description: Learn how to register node, items, and craft recipes using register_node, register_item, and register_craft.
|
||||||
|
redirect_from: /en/chapters/nodes_items_crafting.html
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction <!-- omit in toc -->
|
||||||
|
|
||||||
|
Minetest heavily uses a callback-based modding design. A callback is a function
|
||||||
|
that you give to an API and is called when an event happens. For example, you
|
||||||
|
can provide an `on_punch` function in a node definition to be called when a player
|
||||||
|
punches a node. There are also global callbacks like
|
||||||
|
`minetest.register_on_punchnode` to receive events for all nodes.
|
||||||
|
|
||||||
|
- [Item Callbacks](#item-callbacks)
|
||||||
|
- [on_use](#on_use)
|
||||||
|
- [on_place and on_secondary_use](#on_place-and-on_secondary_use)
|
||||||
|
- [on_drop](#on_drop)
|
||||||
|
- [after_use](#after_use)
|
||||||
|
- [item_place vs place_item](#item_place-vs-place_item)
|
||||||
|
- [Node Callbacks](#node-callbacks)
|
||||||
|
- [Right-clicking and placing a node](#right-clicking-and-placing-a-node)
|
||||||
|
- [Punching and digging](#punching-and-digging)
|
||||||
|
- [...and more!](#and-more)
|
||||||
|
|
||||||
|
|
||||||
|
## Item Callbacks
|
||||||
|
|
||||||
|
When a player has a node, craftitem, or tool in their inventory, they may trigger
|
||||||
|
certain events:
|
||||||
|
|
||||||
|
| Callback | Default binding | Default value |
|
||||||
|
|------------------|---------------------------|----------------------------------------------|
|
||||||
|
| on_use | left-click | nil |
|
||||||
|
| on_place | right-click on a node | `minetest.item_place` |
|
||||||
|
| on_secondary_use | right-click not on a node | `minetest.item_secondary_use` (does nothing) |
|
||||||
|
| on_drop | Q | `minetest.item_drop` |
|
||||||
|
| after_use | digging a node | nil |
|
||||||
|
|
||||||
|
|
||||||
|
### on_use
|
||||||
|
|
||||||
|
Having a use callback prevents the item from being used to dig nodes. One common
|
||||||
|
use of the use callback is for food:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
minetest.register_craftitem("mymod:mudpie", {
|
||||||
|
description = "Alien Mud Pie",
|
||||||
|
inventory_image = "myfood_mudpie.png",
|
||||||
|
on_use = minetest.item_eat(20),
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The number supplied to the minetest.item_eat function is the number of hit
|
||||||
|
points healed when this food is consumed. Each heart icon the player has is
|
||||||
|
worth two hitpoints. A player can usually have up to 10 hearts, which is equal
|
||||||
|
to 20 hitpoints.
|
||||||
|
|
||||||
|
minetest.item_eat() is a function that returns a function, setting it as the
|
||||||
|
on_use callback. This means the code above is equivalent to this:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
minetest.register_craftitem("mymod:mudpie", {
|
||||||
|
description = "Alien Mud Pie",
|
||||||
|
inventory_image = "myfood_mudpie.png",
|
||||||
|
on_use = function(...)
|
||||||
|
return minetest.do_item_eat(20, nil, ...)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
By understanding how item_eat works by simply returning a function, it's
|
||||||
|
possible to modify it to do more complex behaviour like playing a custom sound.
|
||||||
|
|
||||||
|
|
||||||
|
### on_place and on_secondary_use
|
||||||
|
|
||||||
|
The difference between `on_place` and `on_secondary_use` is that `on_place` is
|
||||||
|
called when the player is pointing at a node and `on_secondary_use` when the
|
||||||
|
player isn't.
|
||||||
|
|
||||||
|
Both callbacks are called for all types of items. `on_place` defaults to the
|
||||||
|
`minetest.item_place` function, which handles calling the `on_rightclick`
|
||||||
|
callback of the pointed node or placing the wielded item if it is a node.
|
||||||
|
|
||||||
|
|
||||||
|
### on_drop
|
||||||
|
|
||||||
|
on_drop is called when the player requests to drop an item, for example using
|
||||||
|
the drop key (Q) or dragging it outside of the inventory. It defaults to the
|
||||||
|
`minetest.item_drop` function, which will handle dropping the item.
|
||||||
|
|
||||||
|
|
||||||
|
### after_use
|
||||||
|
|
||||||
|
`after_use` is called when digging a node and allows you to customise how wear
|
||||||
|
is applied to a tool. If after_use doesn't exist, then it is the same as:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
after_use = function(itemstack, user, node, digparams)
|
||||||
|
itemstack:add_wear(digparams.wear)
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## item_place vs place_item
|
||||||
|
|
||||||
|
Minetest's API includes many different built-in callback implementations for you
|
||||||
|
to use. These callbacks are named with the item type first, for example,
|
||||||
|
`minetest.item_place` and `minetest.node_dig`. Some callback implementations are
|
||||||
|
used directly whereas some are functions that return the callback:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
minetest.register_item("mymod:example", {
|
||||||
|
on_place = minetest.item_place,
|
||||||
|
on_use = minetest.item_eat(10),
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Minetest's API also includes built-in functions that _do_ something. These are
|
||||||
|
often named in a confusingly similar way to built-in callback implementations
|
||||||
|
but have the verb first. Examples include `minetest.place_item` and
|
||||||
|
`minetest.dig_node` - these functions allow you to dig and place nodes with a
|
||||||
|
similar effect to players.
|
||||||
|
|
||||||
|
|
||||||
|
## Node Callbacks
|
||||||
|
|
||||||
|
When a node is in an inventory, it uses Item Callbacks, as discussed above. When
|
||||||
|
a node is placed in the world, it uses Node Callbacks. There are quite a lot of
|
||||||
|
node callbacks, too many to discuss in this book. However, quite a few of them
|
||||||
|
will be talked about later in the book.
|
||||||
|
|
||||||
|
Several of the callbacks are related to node operations such as placing and
|
||||||
|
removing from the world. It's important to note that node operation callbacks
|
||||||
|
like these aren't called from bulk changes - those that set a large number of
|
||||||
|
nodes at once - for performance reasons. Therefore, you can't rely on these
|
||||||
|
callbacks to always be called.
|
||||||
|
|
||||||
|
|
||||||
|
### Right-clicking and placing a node
|
||||||
|
|
||||||
|
When the user right-clicks with an item whilst pointing at a node, the item's
|
||||||
|
`on_place` callback is called. By default, this is set to `minetest.item_place`.
|
||||||
|
If the pointed node has an `on_rightclick` callback and sneak (shift) is held,
|
||||||
|
then the `on_rightclick` callback is called. Otherwise, `minetest.item_place`
|
||||||
|
will place the node.
|
||||||
|
|
||||||
|
Placing a node will call both `on_construct` and `after_place_node`.
|
||||||
|
`on_construct` is called by any node set event that wasn't in bulk and is just
|
||||||
|
given the node's position and value .`after_place_node` is only called by node
|
||||||
|
place, and so has more information - such as the placer and itemstack.
|
||||||
|
|
||||||
|
It's important to note that players aren't the only objects that can place
|
||||||
|
nodes; it's common for mobs and mods to place nodes. To account for this,
|
||||||
|
`placer` could be a player, entity, or nil.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
minetest.register_node("mymod:mynode", {
|
||||||
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing),
|
||||||
|
if clicker:is_player() then
|
||||||
|
minetest.chat_send_player(clicker:get_player_name(), "Hello world!")
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_construct = function(pos, node)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_string("infotext", "My node!")
|
||||||
|
end,
|
||||||
|
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||||
|
-- Make sure to check placer
|
||||||
|
if placer and placer:is_player() then
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_string("owner", placer:get_player_name())
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Punching and digging
|
||||||
|
|
||||||
|
Punching is when the player left-clicks for a short period. If the wielded item
|
||||||
|
has an `on_use` callback, this will be called. Otherwise, the `on_punch`
|
||||||
|
callback on the pointed node will be called.
|
||||||
|
|
||||||
|
When the player attempts to dig a node, the `on_dig` callback on the node will be called.
|
||||||
|
This defaults to `minetest.node_dig`, which will check for area protection, wear
|
||||||
|
out the tool, remove the node, and run the `after_dig_node` callback.
|
||||||
|
|
||||||
|
|
||||||
|
```lua
|
||||||
|
minetest.register_node("mymod:mynode", {
|
||||||
|
on_punch = function(pos, node, puncher, pointed_thing)
|
||||||
|
if clicker:is_player() then
|
||||||
|
minetest.chat_send_player(clicker:get_player_name(), "Ow!")
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### ...and more!
|
||||||
|
|
||||||
|
Check out Minetest's Lua API reference for a list of all node callbacks, and
|
||||||
|
more information on the callbacks above.
|
@ -18,8 +18,6 @@ basic requirements for many mods.
|
|||||||
- [Item Aliases](#item-aliases)
|
- [Item Aliases](#item-aliases)
|
||||||
- [Textures](#textures)
|
- [Textures](#textures)
|
||||||
- [Registering a basic node](#registering-a-basic-node)
|
- [Registering a basic node](#registering-a-basic-node)
|
||||||
- [Actions and Callbacks](#actions-and-callbacks)
|
|
||||||
- [on_use](#onuse)
|
|
||||||
- [Crafting](#crafting)
|
- [Crafting](#crafting)
|
||||||
- [Shaped](#shaped)
|
- [Shaped](#shaped)
|
||||||
- [Shapeless](#shapeless)
|
- [Shapeless](#shapeless)
|
||||||
@ -29,25 +27,24 @@ basic requirements for many mods.
|
|||||||
|
|
||||||
## What are Nodes and Items?
|
## What are Nodes and Items?
|
||||||
|
|
||||||
Nodes, craftitems, and tools are all Items.
|
Nodes, craftitems, and tools are all Items. An item is something that could be
|
||||||
An item is something that could be found in an inventory -
|
found in an inventory - even if it isn't possible through normal gameplay.
|
||||||
even though it may not be possible through normal gameplay.
|
|
||||||
|
|
||||||
A node is an item which can be placed or be found in the world.
|
A node is an item that can be placed or be found in the world. Every position
|
||||||
Every position in the world must be occupied with one and only one node -
|
in the world must be occupied with one and only one node - seemingly blank
|
||||||
seemingly blank positions are usually air nodes.
|
positions are usually air nodes.
|
||||||
|
|
||||||
A craftitem can't be placed and is only found in inventories or as a dropped item
|
A craftitem can't be placed and is only found in inventories or as a dropped item
|
||||||
in the world.
|
in the world.
|
||||||
|
|
||||||
A tool has the ability to wear and typically has non-default digging capabilities.
|
A tool has the ability to wear and typically has non-default digging
|
||||||
In the future, it's likely that craftitems and tools will merge into one type of
|
capabilities. In the future, it's likely that craftitems and tools will merge
|
||||||
item, as the distinction between them is rather artificial.
|
into one type of item, as the distinction between them is rather artificial.
|
||||||
|
|
||||||
## Registering Items
|
## Registering Items
|
||||||
|
|
||||||
Item definitions consist of an *item name* and a *definition table*.
|
Item definitions consist of an *item name* and a *definition table*.
|
||||||
The definition table contains attributes which affect the behaviour of the item.
|
The definition table contains attributes that affect the behaviour of the item.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craftitem("modname:itemname", {
|
minetest.register_craftitem("modname:itemname", {
|
||||||
@ -63,25 +60,26 @@ following format:
|
|||||||
|
|
||||||
modname:itemname
|
modname:itemname
|
||||||
|
|
||||||
The modname is the name of the mod in which the item is registered, and the
|
The modname is the name of the mod in which the item is registered, and the item
|
||||||
item name is the name of the item itself.
|
name is the name of the item itself. The item name should be relevant to what
|
||||||
The item name should be relevant to what the item is and can't already be registered.
|
the item is and can't already be registered.
|
||||||
|
|
||||||
|
Both `modname` and `itemname` should only contain lowercase letters, numbers,
|
||||||
|
and underscores.
|
||||||
|
|
||||||
### Item Aliases
|
### Item Aliases
|
||||||
|
|
||||||
Items can also have *aliases* pointing to their name.
|
Items can also have *aliases* pointing to their name. An *alias* is a
|
||||||
An *alias* is a pseudo-item name which results in the engine treating any
|
pseudo-item name that results in the engine treating any occurrences of the
|
||||||
occurrences of the alias as if it were the item name.
|
alias as if it were the item name. There are two main common uses of this:
|
||||||
There are two main common uses of this:
|
|
||||||
|
|
||||||
* Renaming removed items to something else.
|
* Renaming removed items to something else.
|
||||||
There may be unknown nodes in the world and in inventories if an item is
|
There may be unknown nodes in the world and in inventories if an item is
|
||||||
removed from a mod without any corrective code.
|
removed from a mod without any corrective code.
|
||||||
* Adding a shortcut. `/giveme dirt` is easier than `/giveme default:dirt`.
|
* Adding a shortcut. `/giveme dirt` is easier than `/giveme default:dirt`.
|
||||||
|
|
||||||
Registering an alias is pretty simple.
|
Registering an alias is pretty simple. A good way to remember the order of the
|
||||||
A good way to remember the order of the arguments is `from → to` where
|
arguments is `from → to` where *from* is the alias and *to* is the target.
|
||||||
*from* is the alias and *to* is the target.
|
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_alias("dirt", "default:dirt")
|
minetest.register_alias("dirt", "default:dirt")
|
||||||
@ -103,14 +101,16 @@ JPEG textures are supported, but they do not support transparency and are genera
|
|||||||
bad quality at low resolutions.
|
bad quality at low resolutions.
|
||||||
It is often better to use the PNG format.
|
It is often better to use the PNG format.
|
||||||
|
|
||||||
Textures in Minetest are usually 16 by 16 pixels.
|
Textures in Minetest are usually 16 by 16 pixels. They can be any resolution,
|
||||||
They can be any resolution, but it is recommended that they are in the order of 2,
|
but it is recommended that they are in the order of 2, for example, 16, 32, 64,
|
||||||
for example, 16, 32, 64, or 128.
|
or 128. This is because other resolutions may not be supported correctly on
|
||||||
This is because other resolutions may not be supported correctly on older devices,
|
older devices, especially phones, resulting in degraded performance.
|
||||||
resulting in decreased performance.
|
|
||||||
|
|
||||||
## Registering a basic node
|
## Registering a basic node
|
||||||
|
|
||||||
|
Registering nodes is similar to registering items, just with a different
|
||||||
|
function:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("mymod:diamond", {
|
minetest.register_node("mymod:diamond", {
|
||||||
description = "Alien Diamond",
|
description = "Alien Diamond",
|
||||||
@ -120,6 +120,9 @@ minetest.register_node("mymod:diamond", {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Node definitions can contain any property in an item definition, and also
|
||||||
|
contain additional properties specific to nodes.
|
||||||
|
|
||||||
The `tiles` property is a table of texture names the node will use.
|
The `tiles` property is a table of texture names the node will use.
|
||||||
When there is only one texture, this texture is used on every side.
|
When there is only one texture, this texture is used on every side.
|
||||||
To give a different texture per-side, supply the names of 6 textures in this order:
|
To give a different texture per-side, supply the names of 6 textures in this order:
|
||||||
@ -128,7 +131,7 @@ To give a different texture per-side, supply the names of 6 textures in this ord
|
|||||||
(+Y, -Y, +X, -X, +Z, -Z)
|
(+Y, -Y, +X, -X, +Z, -Z)
|
||||||
|
|
||||||
Remember that +Y is upwards in Minetest, as is the convention with
|
Remember that +Y is upwards in Minetest, as is the convention with
|
||||||
3D computer graphics.
|
most 3D computer games.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("mymod:diamond", {
|
minetest.register_node("mymod:diamond", {
|
||||||
@ -152,49 +155,6 @@ The `is_ground_content` attribute allows caves to be generated over the stone.
|
|||||||
This is essential for any node which may be placed during map generation underground.
|
This is essential for any node which may be placed during map generation underground.
|
||||||
Caves are cut out of the world after all the other nodes in an area have generated.
|
Caves are cut out of the world after all the other nodes in an area have generated.
|
||||||
|
|
||||||
## Actions and Callbacks
|
|
||||||
|
|
||||||
Minetest heavily uses a callback-based modding design.
|
|
||||||
Callbacks can be placed in the item definition table to allow response to various
|
|
||||||
different user events.
|
|
||||||
|
|
||||||
### on_use
|
|
||||||
|
|
||||||
By default, the use callback is triggered when a player left-clicks with an item.
|
|
||||||
Having a use callback prevents the item being used to dig nodes.
|
|
||||||
One common use of the use callback is for food:
|
|
||||||
|
|
||||||
```lua
|
|
||||||
minetest.register_craftitem("mymod:mudpie", {
|
|
||||||
description = "Alien Mud Pie",
|
|
||||||
inventory_image = "myfood_mudpie.png",
|
|
||||||
on_use = minetest.item_eat(20),
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
The number supplied to the minetest.item_eat function is the number of hit points
|
|
||||||
healed when this food is consumed.
|
|
||||||
Each heart icon the player has is worth two hitpoints.
|
|
||||||
A player can usually have up to 10 hearts, which is equal to 20 hitpoints.
|
|
||||||
Hitpoints don't have to be integers (whole numbers); they can be decimals.
|
|
||||||
|
|
||||||
minetest.item_eat() is a function which returns a function, setting it
|
|
||||||
as the on_use callback.
|
|
||||||
This means the code above is roughly similar to this:
|
|
||||||
|
|
||||||
```lua
|
|
||||||
minetest.register_craftitem("mymod:mudpie", {
|
|
||||||
description = "Alien Mud Pie",
|
|
||||||
inventory_image = "myfood_mudpie.png",
|
|
||||||
on_use = function(...)
|
|
||||||
return minetest.do_item_eat(20, nil, ...)
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
By understanding how item_eat works by simply returning a function, it's
|
|
||||||
possible to modify it to do more complex behaviour such as play a custom sound.
|
|
||||||
|
|
||||||
## Crafting
|
## Crafting
|
||||||
|
|
||||||
There are several types of crafting recipe available, indicated by the `type`
|
There are several types of crafting recipe available, indicated by the `type`
|
||||||
@ -327,6 +287,7 @@ minetest.register_craft({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Tools, Capabilities, and Dig Types
|
## Tools, Capabilities, and Dig Types
|
||||||
|
|
||||||
Dig types are groups which are used to define how strong a node is when dug
|
Dig types are groups which are used to define how strong a node is when dug
|
||||||
|
@ -34,7 +34,7 @@ layout: compress
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<style>body,html,nav{background:#333}nav,nav li,nav li a{display:block}body,html,main,nav li{margin:0;padding:0}main,nav{position:absolute;top:0}body,html{font-size:17px;color:#000}#container{width:100%;max-width:1100px;margin:auto;position:relative}nav{left:0;width:280px;list-style:none;color:#fff}nav li a{padding:5px;color:#ccc;text-decoration:none}main{left:280px;right:0}article{background:#fff;padding:0 20px 20px}</style>
|
<style>body,html,nav{background:#333}nav,nav li,nav li a{display:block}body,html,main,nav li{margin:0;padding:0}main,nav{position:absolute;top:0}body,html{font-size:17px;color:#000}#container{width:100%;max-width:1100px;margin:auto;position:relative}nav{left:0;width:280px;list-style:none;color:#fff}nav li a{padding:5px;color:#ccc;text-decoration:none}main{left:280px;right:0}article{background:#fff;padding:0 20px 20px}</style>
|
||||||
<link rel="stylesheet" href="{{ page.root }}/static/style.css?v=2">
|
<link rel="stylesheet" href="{{ page.root }}/static/style.css?v=3">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="container">
|
<div id="container">
|
||||||
|
17
_sass/_table.scss
Normal file
17
_sass/_table.scss
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
table td, table th {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
table tr:nth-child(even) {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
table th {
|
||||||
|
padding: 12px 8px;
|
||||||
|
text-align: left;
|
||||||
|
background-color: #04AA6D;
|
||||||
|
color: white;
|
||||||
|
}
|
@ -5,3 +5,4 @@
|
|||||||
@import "content";
|
@import "content";
|
||||||
@import "code";
|
@import "code";
|
||||||
@import "notice";
|
@import "notice";
|
||||||
|
@import "table";
|
||||||
|
Loading…
Reference in New Issue
Block a user