Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b6120063a5 | ||
|
412df5d192 | ||
|
e896108377 | ||
|
05307506a6 |
@ -1,4 +1,4 @@
|
|||||||
# Minetest Modding Book
|
# Luanti Modding Book
|
||||||
|
|
||||||
[![Build status](https://gitlab.com/rubenwardy/minetest_modding_book/badges/master/pipeline.svg)](https://gitlab.com/rubenwardy/minetest_modding_book/pipelines)<br>
|
[![Build status](https://gitlab.com/rubenwardy/minetest_modding_book/badges/master/pipeline.svg)](https://gitlab.com/rubenwardy/minetest_modding_book/pipelines)<br>
|
||||||
[Read Online](https://rubenwardy.com/minetest_modding_book/)
|
[Read Online](https://rubenwardy.com/minetest_modding_book/)
|
||||||
|
@ -130,7 +130,7 @@ programs such as [Geogebra](https://www.geogebra.org).
|
|||||||
The following code registers a simple biome named grasslands biome:
|
The following code registers a simple biome named grasslands biome:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_biome({
|
core.register_biome({
|
||||||
name = "grasslands",
|
name = "grasslands",
|
||||||
node_top = "default:dirt_with_grass",
|
node_top = "default:dirt_with_grass",
|
||||||
depth_top = 1,
|
depth_top = 1,
|
||||||
@ -174,7 +174,7 @@ details for where it can be placed, and how frequently it occurs.
|
|||||||
For example:
|
For example:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_decoration({
|
core.register_decoration({
|
||||||
deco_type = "simple",
|
deco_type = "simple",
|
||||||
place_on = {"base:dirt_with_grass"},
|
place_on = {"base:dirt_with_grass"},
|
||||||
sidelen = 16,
|
sidelen = 16,
|
||||||
@ -199,7 +199,7 @@ Schematic decorations are very similar to simple decoration, but involve the pla
|
|||||||
of a schematic instead of the placement of a single node. For example:
|
of a schematic instead of the placement of a single node. For example:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_decoration({
|
core.register_decoration({
|
||||||
deco_type = "schematic",
|
deco_type = "schematic",
|
||||||
place_on = {"base:desert_sand"},
|
place_on = {"base:desert_sand"},
|
||||||
sidelen = 16,
|
sidelen = 16,
|
||||||
@ -207,7 +207,7 @@ minetest.register_decoration({
|
|||||||
biomes = {"desert"},
|
biomes = {"desert"},
|
||||||
y_max = 200,
|
y_max = 200,
|
||||||
y_min = 1,
|
y_min = 1,
|
||||||
schematic = minetest.get_modpath("plants") .. "/schematics/cactus.mts",
|
schematic = core.get_modpath("plants") .. "/schematics/cactus.mts",
|
||||||
flags = "place_center_x, place_center_z",
|
flags = "place_center_x, place_center_z",
|
||||||
rotation = "random",
|
rotation = "random",
|
||||||
})
|
})
|
||||||
@ -229,7 +229,7 @@ to consider registering mapgen aliases of your own if you are making your own ga
|
|||||||
Mapgen aliases provide information to the core mapgen, and can be registered in the form:
|
Mapgen aliases provide information to the core mapgen, and can be registered in the form:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_alias("mapgen_stone", "base:smoke_stone")
|
core.register_alias("mapgen_stone", "base:smoke_stone")
|
||||||
```
|
```
|
||||||
|
|
||||||
At a minimum you should register:
|
At a minimum you should register:
|
||||||
|
@ -10,8 +10,8 @@ redirect_from:
|
|||||||
mapgen_object:
|
mapgen_object:
|
||||||
level: warning
|
level: warning
|
||||||
title: LVMs and Mapgen
|
title: LVMs and Mapgen
|
||||||
message: Don't use `minetest.get_voxel_manip()` with mapgen, as it can cause glitches.
|
message: Don't use `core.get_voxel_manip()` with mapgen, as it can cause glitches.
|
||||||
Use `minetest.get_mapgen_object("voxelmanip")` instead.
|
Use `core.get_mapgen_object("voxelmanip")` instead.
|
||||||
---
|
---
|
||||||
|
|
||||||
## Introduction <!-- omit in toc -->
|
## Introduction <!-- omit in toc -->
|
||||||
@ -45,7 +45,7 @@ and maximum positions that you need to modify. Then you can create and read into
|
|||||||
an LVM. For example:
|
an LVM. For example:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local vm = minetest.get_voxel_manip()
|
local vm = core.get_voxel_manip()
|
||||||
local emin, emax = vm:read_from_map(pos1, pos2)
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ You can find out the content ID for a particular type of node with
|
|||||||
`get_content_id()`. For example:
|
`get_content_id()`. For example:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local c_stone = minetest.get_content_id("default:stone")
|
local c_stone = core.get_content_id("default:stone")
|
||||||
```
|
```
|
||||||
|
|
||||||
You can then check whether the node is stone:
|
You can then check whether the node is stone:
|
||||||
@ -164,17 +164,17 @@ For setting lighting and param2 data, use the appropriately named
|
|||||||
|
|
||||||
`write_to_map()` takes a Boolean which is true if you want lighting to be
|
`write_to_map()` takes a Boolean which is true if you want lighting to be
|
||||||
calculated. If you pass false, you need to recalculate lighting at a future
|
calculated. If you pass false, you need to recalculate lighting at a future
|
||||||
time using `minetest.fix_light`.
|
time using `core.fix_light`.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local function grass_to_dirt(pos1, pos2)
|
local function grass_to_dirt(pos1, pos2)
|
||||||
local c_dirt = minetest.get_content_id("default:dirt")
|
local c_dirt = core.get_content_id("default:dirt")
|
||||||
local c_grass = minetest.get_content_id("default:dirt_with_grass")
|
local c_grass = core.get_content_id("default:dirt_with_grass")
|
||||||
|
|
||||||
-- Read data into LVM
|
-- Read data into LVM
|
||||||
local vm = minetest.get_voxel_manip()
|
local vm = core.get_voxel_manip()
|
||||||
local emin, emax = vm:read_from_map(pos1, pos2)
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
||||||
local a = VoxelArea:new{
|
local a = VoxelArea:new{
|
||||||
MinEdge = emin,
|
MinEdge = emin,
|
||||||
|
@ -122,13 +122,13 @@ Create an init.lua file with the following content:
|
|||||||
```lua
|
```lua
|
||||||
print("This file will be run at load time!")
|
print("This file will be run at load time!")
|
||||||
|
|
||||||
minetest.register_node("mymod:node", {
|
core.register_node("mymod:node", {
|
||||||
description = "This is a node",
|
description = "This is a node",
|
||||||
tiles = {"mymod_node.png"},
|
tiles = {"mymod_node.png"},
|
||||||
groups = {cracky = 1}
|
groups = {cracky = 1}
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
type = "shapeless",
|
type = "shapeless",
|
||||||
output = "mymod:node 3",
|
output = "mymod:node 3",
|
||||||
recipe = { "default:dirt", "default:stone" },
|
recipe = { "default:dirt", "default:stone" },
|
||||||
|
@ -177,7 +177,7 @@ nicer way to write it.
|
|||||||
The recommended way to include other Lua scripts in a mod is to use *dofile*.
|
The recommended way to include other Lua scripts in a mod is to use *dofile*.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
dofile(minetest.get_modpath("modname") .. "/script.lua")
|
dofile(core.get_modpath("modname") .. "/script.lua")
|
||||||
```
|
```
|
||||||
|
|
||||||
A script can return a value, which is useful for sharing private locals:
|
A script can return a value, which is useful for sharing private locals:
|
||||||
@ -189,7 +189,7 @@ module.message = "Hello World!"
|
|||||||
return module
|
return module
|
||||||
|
|
||||||
-- init.lua
|
-- init.lua
|
||||||
local ret = dofile(minetest.get_modpath("modname") .. "/script.lua")
|
local ret = dofile(core.get_modpath("modname") .. "/script.lua")
|
||||||
print(ret.message) -- Hello world!
|
print(ret.message) -- Hello world!
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ idx: 0.1
|
|||||||
---
|
---
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<h1>Minetest Modding Book</h1>
|
<h1>Luanti Modding Book (formerly Minetest)</h1>
|
||||||
|
|
||||||
<span>by <a href="https://rubenwardy.com" rel="author">rubenwardy</a></span>
|
<span>by <a href="https://rubenwardy.com" rel="author">rubenwardy</a></span>
|
||||||
<span>with editing by <a href="http://rc.minetest.tv/">Shara</a></span>
|
<span>with editing by <a href="http://rc.minetest.tv/">Shara</a></span>
|
||||||
|
@ -12,7 +12,7 @@ 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
|
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
|
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
|
punches a node. There are also global callbacks like
|
||||||
`minetest.register_on_punchnode` to receive events for all nodes.
|
`core.register_on_punchnode` to receive events for all nodes.
|
||||||
|
|
||||||
- [Item Callbacks](#item-callbacks)
|
- [Item Callbacks](#item-callbacks)
|
||||||
- [on_use](#on_use)
|
- [on_use](#on_use)
|
||||||
@ -34,9 +34,9 @@ certain events:
|
|||||||
| Callback | Default binding | Default value |
|
| Callback | Default binding | Default value |
|
||||||
|------------------|---------------------------|----------------------------------------------|
|
|------------------|---------------------------|----------------------------------------------|
|
||||||
| on_use | left-click | nil |
|
| on_use | left-click | nil |
|
||||||
| on_place | right-click on a node | `minetest.item_place` |
|
| on_place | right-click on a node | `core.item_place` |
|
||||||
| on_secondary_use | right-click not on a node | `minetest.item_secondary_use` (does nothing) |
|
| on_secondary_use | right-click not on a node | `core.item_secondary_use` (does nothing) |
|
||||||
| on_drop | Q | `minetest.item_drop` |
|
| on_drop | Q | `core.item_drop` |
|
||||||
| after_use | digging a node | nil |
|
| after_use | digging a node | nil |
|
||||||
|
|
||||||
|
|
||||||
@ -46,27 +46,27 @@ Having a use callback prevents the item from being used to dig nodes. One common
|
|||||||
use of the use callback is for food:
|
use of the use callback is for food:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craftitem("mymod:mudpie", {
|
core.register_craftitem("mymod:mudpie", {
|
||||||
description = "Alien Mud Pie",
|
description = "Alien Mud Pie",
|
||||||
inventory_image = "myfood_mudpie.png",
|
inventory_image = "myfood_mudpie.png",
|
||||||
on_use = minetest.item_eat(20),
|
on_use = core.item_eat(20),
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
The number supplied to the minetest.item_eat function is the number of hit
|
The number supplied to the core.item_eat function is the number of hit
|
||||||
points healed when this food is consumed. Each heart icon the player has is
|
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
|
worth two hitpoints. A player can usually have up to 10 hearts, which is equal
|
||||||
to 20 hitpoints.
|
to 20 hitpoints.
|
||||||
|
|
||||||
minetest.item_eat() is a function that returns a function, setting it as the
|
core.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:
|
on_use callback. This means the code above is equivalent to this:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craftitem("mymod:mudpie", {
|
core.register_craftitem("mymod:mudpie", {
|
||||||
description = "Alien Mud Pie",
|
description = "Alien Mud Pie",
|
||||||
inventory_image = "myfood_mudpie.png",
|
inventory_image = "myfood_mudpie.png",
|
||||||
on_use = function(...)
|
on_use = function(...)
|
||||||
return minetest.do_item_eat(20, nil, ...)
|
return core.do_item_eat(20, nil, ...)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@ -82,7 +82,7 @@ called when the player is pointing at a node and `on_secondary_use` when the
|
|||||||
player isn't.
|
player isn't.
|
||||||
|
|
||||||
Both callbacks are called for all types of items. `on_place` defaults to the
|
Both callbacks are called for all types of items. `on_place` defaults to the
|
||||||
`minetest.item_place` function, which handles calling the `on_rightclick`
|
`core.item_place` function, which handles calling the `on_rightclick`
|
||||||
callback of the pointed node or placing the wielded item if it is a node.
|
callback of the pointed node or placing the wielded item if it is a node.
|
||||||
|
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ callback of the pointed node or placing the wielded item if it is a node.
|
|||||||
|
|
||||||
on_drop is called when the player requests to drop an item, for example using
|
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
|
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.
|
`core.item_drop` function, which will handle dropping the item.
|
||||||
|
|
||||||
|
|
||||||
### after_use
|
### after_use
|
||||||
@ -110,20 +110,20 @@ end
|
|||||||
|
|
||||||
Minetest's API includes many different built-in callback implementations for you
|
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,
|
to use. These callbacks are named with the item type first, for example,
|
||||||
`minetest.item_place` and `minetest.node_dig`. Some callback implementations are
|
`core.item_place` and `core.node_dig`. Some callback implementations are
|
||||||
used directly whereas some are functions that return the callback:
|
used directly whereas some are functions that return the callback:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_item("mymod:example", {
|
core.register_item("mymod:example", {
|
||||||
on_place = minetest.item_place,
|
on_place = core.item_place,
|
||||||
on_use = minetest.item_eat(10),
|
on_use = core.item_eat(10),
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Minetest's API also includes built-in functions that _do_ something. These are
|
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
|
often named in a confusingly similar way to built-in callback implementations
|
||||||
but have the verb first. Examples include `minetest.place_item` and
|
but have the verb first. Examples include `core.place_item` and
|
||||||
`minetest.dig_node` - these functions allow you to dig and place nodes with a
|
`core.dig_node` - these functions allow you to dig and place nodes with a
|
||||||
similar effect to players.
|
similar effect to players.
|
||||||
|
|
||||||
|
|
||||||
@ -144,9 +144,9 @@ callbacks to always be called.
|
|||||||
### Right-clicking and placing a node
|
### Right-clicking and placing a node
|
||||||
|
|
||||||
When the user right-clicks with an item whilst pointing at a node, the item's
|
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`.
|
`on_place` callback is called. By default, this is set to `core.item_place`.
|
||||||
If the pointed node has an `on_rightclick` callback and sneak (shift) is held,
|
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`
|
then the `on_rightclick` callback is called. Otherwise, `core.item_place`
|
||||||
will place the node.
|
will place the node.
|
||||||
|
|
||||||
Placing a node will call both `on_construct` and `after_place_node`.
|
Placing a node will call both `on_construct` and `after_place_node`.
|
||||||
@ -159,20 +159,20 @@ nodes; it's common for mobs and mods to place nodes. To account for this,
|
|||||||
`placer` could be a player, entity, or nil.
|
`placer` could be a player, entity, or nil.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("mymod:mynode", {
|
core.register_node("mymod:mynode", {
|
||||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
if clicker:is_player() then
|
if clicker:is_player() then
|
||||||
minetest.chat_send_player(clicker:get_player_name(), "Hello world!")
|
core.chat_send_player(clicker:get_player_name(), "Hello world!")
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
on_construct = function(pos, node)
|
on_construct = function(pos, node)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = core.get_meta(pos)
|
||||||
meta:set_string("infotext", "My node!")
|
meta:set_string("infotext", "My node!")
|
||||||
end,
|
end,
|
||||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||||
-- Make sure to check placer
|
-- Make sure to check placer
|
||||||
if placer and placer:is_player() then
|
if placer and placer:is_player() then
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = core.get_meta(pos)
|
||||||
meta:set_string("owner", placer:get_player_name())
|
meta:set_string("owner", placer:get_player_name())
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
@ -186,15 +186,15 @@ has an `on_use` callback, this will be called. Otherwise, the `on_punch`
|
|||||||
callback on the pointed node will be called.
|
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.
|
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
|
This defaults to `core.node_dig`, which will check for area protection, wear
|
||||||
out the tool, remove the node, and run the `after_dig_node` callback.
|
out the tool, remove the node, and run the `after_dig_node` callback.
|
||||||
|
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("mymod:mynode", {
|
core.register_node("mymod:mynode", {
|
||||||
on_punch = function(pos, node, puncher, pointed_thing)
|
on_punch = function(pos, node, puncher, pointed_thing)
|
||||||
if puncher:is_player() then
|
if puncher:is_player() then
|
||||||
minetest.chat_send_player(puncher:get_player_name(), "Ow!")
|
core.chat_send_player(puncher:get_player_name(), "Ow!")
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
@ -106,7 +106,7 @@ chest. The node must be loaded because it is stored in
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
on_punch = function(pos, node)
|
on_punch = function(pos, node)
|
||||||
local inv = minetest.get_inventory({ type="node", pos=pos })
|
local inv = core.get_inventory({ type="node", pos=pos })
|
||||||
-- now use the inventory
|
-- now use the inventory
|
||||||
end,
|
end,
|
||||||
```
|
```
|
||||||
@ -128,7 +128,7 @@ Player inventories can be obtained similarly or using a player reference.
|
|||||||
The player must be online to access their inventory.
|
The player must be online to access their inventory.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local inv = minetest.get_inventory({ type="player", name="player1" })
|
local inv = core.get_inventory({ type="player", name="player1" })
|
||||||
-- or
|
-- or
|
||||||
local inv = player:get_inventory()
|
local inv = player:get_inventory()
|
||||||
```
|
```
|
||||||
@ -139,7 +139,7 @@ A detached inventory is one that is independent of players or nodes. Detached
|
|||||||
inventories also don't save over a restart.
|
inventories also don't save over a restart.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local inv = minetest.get_inventory({
|
local inv = core.get_inventory({
|
||||||
type="detached", name="inventory_name" })
|
type="detached", name="inventory_name" })
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ Unlike the other types of inventory, you must first create a detached inventory
|
|||||||
before accessing it:
|
before accessing it:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.create_detached_inventory("inventory_name")
|
core.create_detached_inventory("inventory_name")
|
||||||
```
|
```
|
||||||
|
|
||||||
The `create_detached_inventory` function accepts 3 arguments, where only the
|
The `create_detached_inventory` function accepts 3 arguments, where only the
|
||||||
@ -156,7 +156,7 @@ callbacks, which can be used to control how players interact with the inventory:
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Input only detached inventory
|
-- Input only detached inventory
|
||||||
minetest.create_detached_inventory("inventory_name", {
|
core.create_detached_inventory("inventory_name", {
|
||||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||||
return count -- allow moving
|
return count -- allow moving
|
||||||
end,
|
end,
|
||||||
@ -170,9 +170,9 @@ minetest.create_detached_inventory("inventory_name", {
|
|||||||
end,
|
end,
|
||||||
|
|
||||||
on_put = function(inv, listname, index, stack, player)
|
on_put = function(inv, listname, index, stack, player)
|
||||||
minetest.chat_send_all(player:get_player_name() ..
|
core.chat_send_all(player:get_player_name() ..
|
||||||
" gave " .. stack:to_string() ..
|
" gave " .. stack:to_string() ..
|
||||||
" to the donation chest from " .. minetest.pos_to_string(player:get_pos()))
|
" to the donation chest from " .. core.pos_to_string(player:get_pos()))
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
@ -19,7 +19,7 @@ In the previous chapter, the concept of nodes and items was introduced, but a
|
|||||||
full definition of a node wasn't given. The Minetest world is a 3D grid of
|
full definition of a node wasn't given. The Minetest world is a 3D grid of
|
||||||
positions. Each position is called a node, and consists of the node type
|
positions. Each position is called a node, and consists of the node type
|
||||||
(name) and two parameters (param1 and param2). The function
|
(name) and two parameters (param1 and param2). The function
|
||||||
`minetest.register_node` is a bit misleading in that it doesn't actually
|
`core.register_node` is a bit misleading in that it doesn't actually
|
||||||
register a node - it registers a new *type* of node.
|
register a node - it registers a new *type* of node.
|
||||||
|
|
||||||
The node params are used to control how a node is individually rendered.
|
The node params are used to control how a node is individually rendered.
|
||||||
@ -60,13 +60,13 @@ leaf nodes. You can use the allfaces_optional drawtype to allow users to opt-out
|
|||||||
of the slower drawing, in which case it'll act like a normal node.
|
of the slower drawing, in which case it'll act like a normal node.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("mymod:diamond", {
|
core.register_node("mymod:diamond", {
|
||||||
description = "Alien Diamond",
|
description = "Alien Diamond",
|
||||||
tiles = {"mymod_diamond.png"},
|
tiles = {"mymod_diamond.png"},
|
||||||
groups = {cracky = 3},
|
groups = {cracky = 3},
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("default:leaves", {
|
core.register_node("default:leaves", {
|
||||||
description = "Leaves",
|
description = "Leaves",
|
||||||
drawtype = "allfaces_optional",
|
drawtype = "allfaces_optional",
|
||||||
tiles = {"default_leaves.png"}
|
tiles = {"default_leaves.png"}
|
||||||
@ -92,7 +92,7 @@ drawtype would result in the ability to see through the world.
|
|||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("default:obsidian_glass", {
|
core.register_node("default:obsidian_glass", {
|
||||||
description = "Obsidian Glass",
|
description = "Obsidian Glass",
|
||||||
drawtype = "glasslike",
|
drawtype = "glasslike",
|
||||||
tiles = {"default_obsidian_glass.png"},
|
tiles = {"default_obsidian_glass.png"},
|
||||||
@ -120,11 +120,11 @@ You can use the glasslike_framed_optional drawtype to allow the user to *opt-in*
|
|||||||
to the framed appearance.
|
to the framed appearance.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("default:glass", {
|
core.register_node("default:glass", {
|
||||||
description = "Glass",
|
description = "Glass",
|
||||||
drawtype = "glasslike_framed",
|
drawtype = "glasslike_framed",
|
||||||
tiles = {"default_glass.png", "default_glass_detail.png"},
|
tiles = {"default_glass.png", "default_glass_detail.png"},
|
||||||
inventory_image = minetest.inventorycube("default_glass.png"),
|
inventory_image = core.inventorycube("default_glass.png"),
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
sunlight_propagates = true, -- Sunlight can shine through block
|
sunlight_propagates = true, -- Sunlight can shine through block
|
||||||
groups = {cracky = 3, oddly_breakable_by_hand = 3},
|
groups = {cracky = 3, oddly_breakable_by_hand = 3},
|
||||||
@ -138,7 +138,7 @@ minetest.register_node("default:glass", {
|
|||||||
These nodes are not rendered and thus have no textures.
|
These nodes are not rendered and thus have no textures.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("myair:air", {
|
core.register_node("myair:air", {
|
||||||
description = "MyAir (you hacker you!)",
|
description = "MyAir (you hacker you!)",
|
||||||
drawtype = "airlike",
|
drawtype = "airlike",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
@ -192,11 +192,11 @@ another for flowing liquid.
|
|||||||
```lua
|
```lua
|
||||||
-- Some properties have been removed as they are beyond
|
-- Some properties have been removed as they are beyond
|
||||||
-- the scope of this chapter.
|
-- the scope of this chapter.
|
||||||
minetest.register_node("default:water_source", {
|
core.register_node("default:water_source", {
|
||||||
drawtype = "liquid",
|
drawtype = "liquid",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
|
|
||||||
inventory_image = minetest.inventorycube("default_water.png"),
|
inventory_image = core.inventorycube("default_water.png"),
|
||||||
-- ^ this is required to stop the inventory image from being animated
|
-- ^ this is required to stop the inventory image from being animated
|
||||||
|
|
||||||
tiles = {
|
tiles = {
|
||||||
@ -271,7 +271,7 @@ Node boxes allow you to create a node which is not cubic, but is instead made ou
|
|||||||
of as many cuboids as you like.
|
of as many cuboids as you like.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("stairs:stair_stone", {
|
core.register_node("stairs:stair_stone", {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
node_box = {
|
node_box = {
|
||||||
@ -305,7 +305,7 @@ create node boxes by dragging the edges, it is more visual than doing it by hand
|
|||||||
Sometimes you want different nodeboxes for when it is placed on the floor, wall, or ceiling like with torches.
|
Sometimes you want different nodeboxes for when it is placed on the floor, wall, or ceiling like with torches.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("default:sign_wall", {
|
core.register_node("default:sign_wall", {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
node_box = {
|
node_box = {
|
||||||
type = "wallmounted",
|
type = "wallmounted",
|
||||||
@ -341,7 +341,7 @@ invisible but still rendered.
|
|||||||
You can register a mesh node as so:
|
You can register a mesh node as so:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("mymod:meshy", {
|
core.register_node("mymod:meshy", {
|
||||||
drawtype = "mesh",
|
drawtype = "mesh",
|
||||||
|
|
||||||
-- Holds the texture for each "material"
|
-- Holds the texture for each "material"
|
||||||
@ -370,7 +370,7 @@ instead use the `nodebox` drawtype to provide a 3D effect. The `signlike` drawty
|
|||||||
is, however, commonly used by ladders.
|
is, however, commonly used by ladders.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("default:ladder_wood", {
|
core.register_node("default:ladder_wood", {
|
||||||
drawtype = "signlike",
|
drawtype = "signlike",
|
||||||
|
|
||||||
tiles = {"default_ladder_wood.png"},
|
tiles = {"default_ladder_wood.png"},
|
||||||
@ -397,7 +397,7 @@ minetest.register_node("default:ladder_wood", {
|
|||||||
Plantlike nodes draw their tiles in an X like pattern.
|
Plantlike nodes draw their tiles in an X like pattern.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("default:papyrus", {
|
core.register_node("default:papyrus", {
|
||||||
drawtype = "plantlike",
|
drawtype = "plantlike",
|
||||||
|
|
||||||
-- Only one texture used
|
-- Only one texture used
|
||||||
@ -423,7 +423,7 @@ and ceilings.
|
|||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("mymod:clingere", {
|
core.register_node("mymod:clingere", {
|
||||||
drawtype = "firelike",
|
drawtype = "firelike",
|
||||||
|
|
||||||
-- Only one texture used
|
-- Only one texture used
|
||||||
|
@ -48,7 +48,7 @@ Item definitions consist of an *item name* and a *definition table*.
|
|||||||
The definition table contains attributes that 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", {
|
core.register_craftitem("modname:itemname", {
|
||||||
description = "My Special Item",
|
description = "My Special Item",
|
||||||
inventory_image = "modname_itemname.png"
|
inventory_image = "modname_itemname.png"
|
||||||
})
|
})
|
||||||
@ -83,7 +83,7 @@ Registering an alias is pretty simple. A good way to remember the order of the
|
|||||||
arguments is `from → to` where *from* is the alias and *to* is the target.
|
arguments is `from → to` where *from* is the alias and *to* is the target.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_alias("dirt", "default:dirt")
|
core.register_alias("dirt", "default:dirt")
|
||||||
```
|
```
|
||||||
|
|
||||||
Mods need to make sure to resolve aliases before dealing directly with item names,
|
Mods need to make sure to resolve aliases before dealing directly with item names,
|
||||||
@ -91,7 +91,7 @@ as the engine won't do this.
|
|||||||
This is pretty simple though:
|
This is pretty simple though:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
itemname = minetest.registered_aliases[itemname] or itemname
|
itemname = core.registered_aliases[itemname] or itemname
|
||||||
```
|
```
|
||||||
|
|
||||||
### Textures
|
### Textures
|
||||||
@ -113,7 +113,7 @@ Registering nodes is similar to registering items, just with a different
|
|||||||
function:
|
function:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("mymod:diamond", {
|
core.register_node("mymod:diamond", {
|
||||||
description = "Alien Diamond",
|
description = "Alien Diamond",
|
||||||
tiles = {"mymod_diamond.png"},
|
tiles = {"mymod_diamond.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
@ -135,7 +135,7 @@ Remember that +Y is upwards in Minetest, as is the convention with
|
|||||||
most 3D computer games.
|
most 3D computer games.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("mymod:diamond", {
|
core.register_node("mymod:diamond", {
|
||||||
description = "Alien Diamond",
|
description = "Alien Diamond",
|
||||||
tiles = {
|
tiles = {
|
||||||
"mymod_diamond_up.png", -- y+
|
"mymod_diamond_up.png", -- y+
|
||||||
@ -178,7 +178,7 @@ pattern to work. In the example below, the fragments need to be in a
|
|||||||
chair-like pattern for the craft to work.
|
chair-like pattern for the craft to work.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
type = "shaped",
|
type = "shaped",
|
||||||
output = "mymod:diamond_chair 99",
|
output = "mymod:diamond_chair 99",
|
||||||
recipe = {
|
recipe = {
|
||||||
@ -196,7 +196,7 @@ If this empty column shouldn't be required, then the empty strings can be left
|
|||||||
out like so:
|
out like so:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
output = "mymod:diamond_chair 99",
|
output = "mymod:diamond_chair 99",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"mymod:diamond_fragments", "" },
|
{"mymod:diamond_fragments", "" },
|
||||||
@ -215,7 +215,7 @@ Shapeless recipes are a type of recipe which is used when it doesn't matter
|
|||||||
where the ingredients are placed, just that they're there.
|
where the ingredients are placed, just that they're there.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
type = "shapeless",
|
type = "shapeless",
|
||||||
output = "mymod:diamond 3",
|
output = "mymod:diamond 3",
|
||||||
recipe = {
|
recipe = {
|
||||||
@ -232,7 +232,7 @@ Recipes with the type "cooking" are not made in the crafting grid,
|
|||||||
but are cooked in furnaces, or other cooking tools that might be found in mods.
|
but are cooked in furnaces, or other cooking tools that might be found in mods.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
type = "cooking",
|
type = "cooking",
|
||||||
output = "mymod:diamond_fragments",
|
output = "mymod:diamond_fragments",
|
||||||
recipe = "default:coalblock",
|
recipe = "default:coalblock",
|
||||||
@ -254,7 +254,7 @@ This type is an accompaniment to the cooking type, as it defines
|
|||||||
what can be burned in furnaces and other cooking tools from mods.
|
what can be burned in furnaces and other cooking tools from mods.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
type = "fuel",
|
type = "fuel",
|
||||||
recipe = "mymod:diamond",
|
recipe = "mymod:diamond",
|
||||||
burntime = 300,
|
burntime = 300,
|
||||||
@ -281,7 +281,7 @@ Secondly, groups can be used in a craft recipe instead of an item name to allow
|
|||||||
any item in the group to be used.
|
any item in the group to be used.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
type = "shapeless",
|
type = "shapeless",
|
||||||
output = "mymod:diamond_thing 3",
|
output = "mymod:diamond_thing 3",
|
||||||
recipe = {"group:wood", "mymod:diamond"}
|
recipe = {"group:wood", "mymod:diamond"}
|
||||||
@ -322,7 +322,7 @@ If the item a player is currently wielding doesn't have an explicit tool
|
|||||||
capability, then the capability of the current hand is used instead.
|
capability, then the capability of the current hand is used instead.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_tool("mymod:tool", {
|
core.register_tool("mymod:tool", {
|
||||||
description = "My Tool",
|
description = "My Tool",
|
||||||
inventory_image = "mymod_tool.png",
|
inventory_image = "mymod_tool.png",
|
||||||
tool_capabilities = {
|
tool_capabilities = {
|
||||||
|
@ -48,7 +48,7 @@ loaded from the world database outside of the generation limit.
|
|||||||
You can read from the map once you have a position:
|
You can read from the map once you have a position:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local node = minetest.get_node({ x = 1, y = 3, z = 4 })
|
local node = core.get_node({ x = 1, y = 3, z = 4 })
|
||||||
print(dump(node)) --> { name=.., param1=.., param2=.. }
|
print(dump(node)) --> { name=.., param1=.., param2=.. }
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ The function will always return a table containing the node information:
|
|||||||
It's worth noting that the function won't load the containing block if the block
|
It's worth noting that the function won't load the containing block if the block
|
||||||
is inactive, but will instead return a table with `name` being `ignore`.
|
is inactive, but will instead return a table with `name` being `ignore`.
|
||||||
|
|
||||||
You can use `minetest.get_node_or_nil` instead, which will return `nil` rather
|
You can use `core.get_node_or_nil` instead, which will return `nil` rather
|
||||||
than a table with a name of `ignore`. It still won't load the block, however.
|
than a table with a name of `ignore`. It still won't load the block, however.
|
||||||
This may still return `ignore` if a block actually contains ignore.
|
This may still return `ignore` if a block actually contains ignore.
|
||||||
This will happen near the edge of the map as defined by the map generation
|
This will happen near the edge of the map as defined by the map generation
|
||||||
@ -77,15 +77,15 @@ For example, say we wanted to make a certain type of plant that grows
|
|||||||
better near mese; you would need to search for any nearby mese nodes,
|
better near mese; you would need to search for any nearby mese nodes,
|
||||||
and adapt the growth rate accordingly.
|
and adapt the growth rate accordingly.
|
||||||
|
|
||||||
`minetest.find_node_near` will return the first found node in a certain radius
|
`core.find_node_near` will return the first found node in a certain radius
|
||||||
which matches the node names or groups given. In the following example,
|
which matches the node names or groups given. In the following example,
|
||||||
we look for a mese node within 5 nodes of the position:
|
we look for a mese node within 5 nodes of the position:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local grow_speed = 1
|
local grow_speed = 1
|
||||||
local node_pos = minetest.find_node_near(pos, 5, { "default:mese" })
|
local node_pos = core.find_node_near(pos, 5, { "default:mese" })
|
||||||
if node_pos then
|
if node_pos then
|
||||||
minetest.chat_send_all("Node found at: " .. dump(node_pos))
|
core.chat_send_all("Node found at: " .. dump(node_pos))
|
||||||
grow_speed = 2
|
grow_speed = 2
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
@ -97,7 +97,7 @@ nearby. You should then use a function that can find multiple nodes in the area:
|
|||||||
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
||||||
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
||||||
local pos_list =
|
local pos_list =
|
||||||
minetest.find_nodes_in_area(pos1, pos2, { "default:mese" })
|
core.find_nodes_in_area(pos1, pos2, { "default:mese" })
|
||||||
local grow_speed = 1 + #pos_list
|
local grow_speed = 1 + #pos_list
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ order to fix this, we will need to manually check the range ourselves:
|
|||||||
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
||||||
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
||||||
local pos_list =
|
local pos_list =
|
||||||
minetest.find_nodes_in_area(pos1, pos2, { "default:mese" })
|
core.find_nodes_in_area(pos1, pos2, { "default:mese" })
|
||||||
local grow_speed = 1
|
local grow_speed = 1
|
||||||
for i=1, #pos_list do
|
for i=1, #pos_list do
|
||||||
local delta = vector.subtract(pos_list[i], pos)
|
local delta = vector.subtract(pos_list[i], pos)
|
||||||
@ -138,9 +138,9 @@ lighting to be recalculated and node callbacks to run, which means that set_node
|
|||||||
is fairly slow for large numbers of nodes.
|
is fairly slow for large numbers of nodes.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.set_node({ x = 1, y = 3, z = 4 }, { name = "default:mese" })
|
core.set_node({ x = 1, y = 3, z = 4 }, { name = "default:mese" })
|
||||||
|
|
||||||
local node = minetest.get_node({ x = 1, y = 3, z = 4 })
|
local node = core.get_node({ x = 1, y = 3, z = 4 })
|
||||||
print(node.name) --> default:mese
|
print(node.name) --> default:mese
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ two.
|
|||||||
You can set a node without deleting metadata or the inventory like so:
|
You can set a node without deleting metadata or the inventory like so:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.swap_node({ x = 1, y = 3, z = 4 }, { name = "default:mese" })
|
core.swap_node({ x = 1, y = 3, z = 4 }, { name = "default:mese" })
|
||||||
```
|
```
|
||||||
|
|
||||||
### Removing Nodes
|
### Removing Nodes
|
||||||
@ -163,15 +163,15 @@ A node must always be present. To remove a node, you set the position to `air`.
|
|||||||
The following two lines will both remove a node, and are both identical:
|
The following two lines will both remove a node, and are both identical:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.remove_node(pos)
|
core.remove_node(pos)
|
||||||
minetest.set_node(pos, { name = "air" })
|
core.set_node(pos, { name = "air" })
|
||||||
```
|
```
|
||||||
|
|
||||||
In fact, remove_node is just a helper function that calls set_node with `"air"`.
|
In fact, remove_node is just a helper function that calls set_node with `"air"`.
|
||||||
|
|
||||||
## Loading Blocks
|
## Loading Blocks
|
||||||
|
|
||||||
You can use `minetest.emerge_area` to load map blocks. Emerge area is asynchronous,
|
You can use `core.emerge_area` to load map blocks. Emerge area is asynchronous,
|
||||||
meaning the blocks won't be loaded instantly. Instead, they will be loaded
|
meaning the blocks won't be loaded instantly. Instead, they will be loaded
|
||||||
soon in the future, and the callback will be called each time.
|
soon in the future, and the callback will be called each time.
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ local pos1 = vector.subtract(pos, halfsize)
|
|||||||
local pos2 = vector.add (pos, halfsize)
|
local pos2 = vector.add (pos, halfsize)
|
||||||
|
|
||||||
local context = {} -- persist data between callback calls
|
local context = {} -- persist data between callback calls
|
||||||
minetest.emerge_area(pos1, pos2, emerge_callback, context)
|
core.emerge_area(pos1, pos2, emerge_callback, context)
|
||||||
```
|
```
|
||||||
|
|
||||||
Minetest will call `emerge_callback` whenever it loads a block, with some
|
Minetest will call `emerge_callback` whenever it loads a block, with some
|
||||||
@ -202,12 +202,12 @@ local function emerge_callback(pos, action,
|
|||||||
|
|
||||||
-- Send progress message
|
-- Send progress message
|
||||||
if context.total_blocks == context.loaded_blocks then
|
if context.total_blocks == context.loaded_blocks then
|
||||||
minetest.chat_send_all("Finished loading blocks!")
|
core.chat_send_all("Finished loading blocks!")
|
||||||
else
|
else
|
||||||
local perc = 100 * context.loaded_blocks / context.total_blocks
|
local perc = 100 * context.loaded_blocks / context.total_blocks
|
||||||
local msg = string.format("Loading blocks %d/%d (%.2f%%)",
|
local msg = string.format("Loading blocks %d/%d (%.2f%%)",
|
||||||
context.loaded_blocks, context.total_blocks, perc)
|
context.loaded_blocks, context.total_blocks, perc)
|
||||||
minetest.chat_send_all(msg)
|
core.chat_send_all(msg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
@ -226,7 +226,7 @@ local halfsize = { x = 10, y = 10, z = 10 }
|
|||||||
local pos1 = vector.subtract(pos, halfsize)
|
local pos1 = vector.subtract(pos, halfsize)
|
||||||
local pos2 = vector.add (pos, halfsize)
|
local pos2 = vector.add (pos, halfsize)
|
||||||
|
|
||||||
minetest.delete_area(pos1, pos2)
|
core.delete_area(pos1, pos2)
|
||||||
```
|
```
|
||||||
|
|
||||||
This will delete all map blocks in that area, *inclusive*. This means that some
|
This will delete all map blocks in that area, *inclusive*. This means that some
|
||||||
|
@ -48,7 +48,7 @@ which is referred to as a Lua entity, as discussed later.
|
|||||||
`get_pos` and `set_pos` exist to allow you to get and set an entity's position.
|
`get_pos` and `set_pos` exist to allow you to get and set an entity's position.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local object = minetest.get_player_by_name("bob")
|
local object = core.get_player_by_name("bob")
|
||||||
local pos = object:get_pos()
|
local pos = object:get_pos()
|
||||||
object:set_pos({ x = pos.x, y = pos.y + 1, z = pos.z })
|
object:set_pos({ x = pos.x, y = pos.y + 1, z = pos.z })
|
||||||
```
|
```
|
||||||
@ -152,7 +152,7 @@ Both an ObjectRef and an entity table provide ways to get the counterpart:
|
|||||||
```lua
|
```lua
|
||||||
local entity = object:get_luaentity()
|
local entity = object:get_luaentity()
|
||||||
local object = entity.object
|
local object = entity.object
|
||||||
print("entity is at " .. minetest.pos_to_string(object:get_pos()))
|
print("entity is at " .. core.pos_to_string(object:get_pos()))
|
||||||
```
|
```
|
||||||
|
|
||||||
There are a number of available callbacks for use with entities.
|
There are a number of available callbacks for use with entities.
|
||||||
@ -164,9 +164,9 @@ function MyEntity:on_step(dtime)
|
|||||||
local pos_down = vector.subtract(pos, vector.new(0, 1, 0))
|
local pos_down = vector.subtract(pos, vector.new(0, 1, 0))
|
||||||
|
|
||||||
local delta
|
local delta
|
||||||
if minetest.get_node(pos_down).name == "air" then
|
if core.get_node(pos_down).name == "air" then
|
||||||
delta = vector.new(0, -1, 0)
|
delta = vector.new(0, -1, 0)
|
||||||
elseif minetest.get_node(pos).name == "air" then
|
elseif core.get_node(pos).name == "air" then
|
||||||
delta = vector.new(0, 0, 1)
|
delta = vector.new(0, 0, 1)
|
||||||
else
|
else
|
||||||
delta = vector.new(0, 1, 0)
|
delta = vector.new(0, 1, 0)
|
||||||
@ -178,7 +178,7 @@ function MyEntity:on_step(dtime)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MyEntity:on_punch(hitter)
|
function MyEntity:on_punch(hitter)
|
||||||
minetest.chat_send_player(hitter:get_player_name(), self.message)
|
core.chat_send_player(hitter:get_player_name(), self.message)
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -192,14 +192,14 @@ needs to stored.
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
function MyEntity:get_staticdata()
|
function MyEntity:get_staticdata()
|
||||||
return minetest.write_json({
|
return core.write_json({
|
||||||
message = self.message,
|
message = self.message,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function MyEntity:on_activate(staticdata, dtime_s)
|
function MyEntity:on_activate(staticdata, dtime_s)
|
||||||
if staticdata ~= "" and staticdata ~= nil then
|
if staticdata ~= "" and staticdata ~= nil then
|
||||||
local data = minetest.parse_json(staticdata) or {}
|
local data = core.parse_json(staticdata) or {}
|
||||||
self:set_message(data.message)
|
self:set_message(data.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -217,14 +217,14 @@ This means that staticdata could be empty.
|
|||||||
Finally, you need to register the type table using the aptly named `register_entity`.
|
Finally, you need to register the type table using the aptly named `register_entity`.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_entity("mymod:entity", MyEntity)
|
core.register_entity("mymod:entity", MyEntity)
|
||||||
```
|
```
|
||||||
|
|
||||||
The entity can be spawned by a mod like so:
|
The entity can be spawned by a mod like so:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local pos = { x = 1, y = 2, z = 3 }
|
local pos = { x = 1, y = 2, z = 3 }
|
||||||
local obj = minetest.add_entity(pos, "mymod:entity", nil)
|
local obj = core.add_entity(pos, "mymod:entity", nil)
|
||||||
```
|
```
|
||||||
|
|
||||||
The third parameter is the initial staticdata.
|
The third parameter is the initial staticdata.
|
||||||
|
@ -53,7 +53,7 @@ The data itself, such as a node's type or an stack's count, is not metadata.
|
|||||||
If you know the position of a node, you can retrieve its metadata:
|
If you know the position of a node, you can retrieve its metadata:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local meta = minetest.get_meta({ x = 1, y = 2, z = 3 })
|
local meta = core.get_meta({ x = 1, y = 2, z = 3 })
|
||||||
```
|
```
|
||||||
|
|
||||||
Player and ItemStack metadata are obtained using `get_meta()`:
|
Player and ItemStack metadata are obtained using `get_meta()`:
|
||||||
@ -99,7 +99,7 @@ This is useful when showing the ownership or status of a node.
|
|||||||
|
|
||||||
`description` is used in ItemStack Metadata to override the description when
|
`description` is used in ItemStack Metadata to override the description when
|
||||||
hovering over the stack in an inventory.
|
hovering over the stack in an inventory.
|
||||||
You can use colours by encoding them with `minetest.colorize()`.
|
You can use colours by encoding them with `core.colorize()`.
|
||||||
|
|
||||||
`owner` is a common key used to store the username of the player that owns the
|
`owner` is a common key used to store the username of the player that owns the
|
||||||
item or node.
|
item or node.
|
||||||
@ -116,9 +116,9 @@ with another program.
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
local data = { username = "player1", score = 1234 }
|
local data = { username = "player1", score = 1234 }
|
||||||
meta:set_string("foo", minetest.serialize(data))
|
meta:set_string("foo", core.serialize(data))
|
||||||
|
|
||||||
data = minetest.deserialize(minetest:get_string("foo"))
|
data = core.deserialize(meta:get_string("foo"))
|
||||||
```
|
```
|
||||||
|
|
||||||
### Private Metadata
|
### Private Metadata
|
||||||
@ -149,7 +149,7 @@ Mod storage is per-mod, and can only be obtained during load time in order to
|
|||||||
know which mod is requesting it.
|
know which mod is requesting it.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local storage = minetest.get_mod_storage()
|
local storage = core.get_mod_storage()
|
||||||
```
|
```
|
||||||
|
|
||||||
You can now manipulate the storage just like metadata:
|
You can now manipulate the storage just like metadata:
|
||||||
@ -169,10 +169,10 @@ it is used.
|
|||||||
local backend
|
local backend
|
||||||
if use_database then
|
if use_database then
|
||||||
backend =
|
backend =
|
||||||
dofile(minetest.get_modpath("mymod") .. "/backend_sqlite.lua")
|
dofile(core.get_modpath("mymod") .. "/backend_sqlite.lua")
|
||||||
else
|
else
|
||||||
backend =
|
backend =
|
||||||
dofile(minetest.get_modpath("mymod") .. "/backend_storage.lua")
|
dofile(core.get_modpath("mymod") .. "/backend_storage.lua")
|
||||||
end
|
end
|
||||||
|
|
||||||
backend.get_foo("a")
|
backend.get_foo("a")
|
||||||
@ -182,15 +182,15 @@ backend.set_foo("a", { score = 3 })
|
|||||||
The backend_storage.lua file should include a mod storage implementation:
|
The backend_storage.lua file should include a mod storage implementation:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local storage = minetest.get_mod_storage()
|
local storage = core.get_mod_storage()
|
||||||
local backend = {}
|
local backend = {}
|
||||||
|
|
||||||
function backend.set_foo(key, value)
|
function backend.set_foo(key, value)
|
||||||
storage:set_string(key, minetest.serialize(value))
|
storage:set_string(key, core.serialize(value))
|
||||||
end
|
end
|
||||||
|
|
||||||
function backend.get_foo(key)
|
function backend.get_foo(key)
|
||||||
return minetest.deserialize(storage:get_string(key))
|
return core.deserialize(storage:get_string(key))
|
||||||
end
|
end
|
||||||
|
|
||||||
return backend
|
return backend
|
||||||
@ -207,7 +207,7 @@ Insecure environments will be covered in more detail in the
|
|||||||
[Security](../quality/security.html) chapter.
|
[Security](../quality/security.html) chapter.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local ie = minetest.request_insecure_environment()
|
local ie = core.request_insecure_environment()
|
||||||
assert(ie, "Please add mymod to secure.trusted_mods in the settings")
|
assert(ie, "Please add mymod to secure.trusted_mods in the settings")
|
||||||
|
|
||||||
local _sql = ie.require("lsqlite3")
|
local _sql = ie.require("lsqlite3")
|
||||||
@ -244,4 +244,4 @@ They're well suited for large data sets.
|
|||||||
## Your Turn
|
## Your Turn
|
||||||
|
|
||||||
* Make a node which disappears after it has been punched five times.
|
* Make a node which disappears after it has been punched five times.
|
||||||
(Use `on_punch` in the node definition and `minetest.set_node`.)
|
(Use `on_punch` in the node definition and `core.set_node`.)
|
||||||
|
@ -37,7 +37,7 @@ Node timers are directly tied to a single node.
|
|||||||
You can manage node timers by obtaining a NodeTimerRef object.
|
You can manage node timers by obtaining a NodeTimerRef object.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local timer = minetest.get_node_timer(pos)
|
local timer = core.get_node_timer(pos)
|
||||||
timer:start(10.5) -- in seconds
|
timer:start(10.5) -- in seconds
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -45,9 +45,9 @@ When a node timer is up, the `on_timer` method in the node's definition table wi
|
|||||||
be called. The method only takes a single parameter, the position of the node:
|
be called. The method only takes a single parameter, the position of the node:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("autodoors:door_open", {
|
core.register_node("autodoors:door_open", {
|
||||||
on_timer = function(pos)
|
on_timer = function(pos)
|
||||||
minetest.set_node(pos, { name = "autodoors:door" })
|
core.set_node(pos, { name = "autodoors:door" })
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
@ -68,15 +68,15 @@ has a chance to appear near water.
|
|||||||
|
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("aliens:grass", {
|
core.register_node("aliens:grass", {
|
||||||
description = "Alien Grass",
|
description = "Alien Grass",
|
||||||
light_source = 3, -- The node radiates light. Min 0, max 14
|
light_source = 3, -- The node radiates light. Min 0, max 14
|
||||||
tiles = {"aliens_grass.png"},
|
tiles = {"aliens_grass.png"},
|
||||||
groups = {choppy=1},
|
groups = {choppy=1},
|
||||||
on_use = minetest.item_eat(20)
|
on_use = core.item_eat(20)
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_abm({
|
core.register_abm({
|
||||||
nodenames = {"default:dirt_with_grass"},
|
nodenames = {"default:dirt_with_grass"},
|
||||||
neighbors = {"default:water_source", "default:water_flowing"},
|
neighbors = {"default:water_source", "default:water_flowing"},
|
||||||
interval = 10.0, -- Run every 10 seconds
|
interval = 10.0, -- Run every 10 seconds
|
||||||
@ -84,7 +84,7 @@ minetest.register_abm({
|
|||||||
action = function(pos, node, active_object_count,
|
action = function(pos, node, active_object_count,
|
||||||
active_object_count_wider)
|
active_object_count_wider)
|
||||||
local pos = {x = pos.x, y = pos.y + 1, z = pos.z}
|
local pos = {x = pos.x, y = pos.y + 1, z = pos.z}
|
||||||
minetest.set_node(pos, {name = "aliens:grass"})
|
core.set_node(pos, {name = "aliens:grass"})
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@ -93,7 +93,7 @@ This ABM runs every ten seconds, and for each matching node, there is
|
|||||||
a 1 in 50 chance of it running.
|
a 1 in 50 chance of it running.
|
||||||
If the ABM runs on a node, an alien grass node is placed above it.
|
If the ABM runs on a node, an alien grass node is placed above it.
|
||||||
Please be warned, this will delete any node previously located in that position.
|
Please be warned, this will delete any node previously located in that position.
|
||||||
To prevent this you should include a check using minetest.get_node to make sure there is space for the grass.
|
To prevent this you should include a check using core.get_node to make sure there is space for the grass.
|
||||||
|
|
||||||
Specifying a neighbour is optional.
|
Specifying a neighbour is optional.
|
||||||
If you specify multiple neighbours, only one of them needs to be
|
If you specify multiple neighbours, only one of them needs to be
|
||||||
|
@ -14,7 +14,7 @@ cmd_online:
|
|||||||
bridge allows players to run commands without joining the game.
|
bridge allows players to run commands without joining the game.
|
||||||
|
|
||||||
So make sure that you don't assume that the player is online.
|
So make sure that you don't assume that the player is online.
|
||||||
You can check by seeing if `minetest.get_player_by_name` returns a player.
|
You can check by seeing if `core.get_player_by_name` returns a player.
|
||||||
|
|
||||||
cb_cmdsprivs:
|
cb_cmdsprivs:
|
||||||
level: warning
|
level: warning
|
||||||
@ -47,7 +47,7 @@ sending messages, intercepting messages, and registering chat commands.
|
|||||||
To send a message to every player in the game, call the `chat_send_all` function.
|
To send a message to every player in the game, call the `chat_send_all` function.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.chat_send_all("This is a chat message to all players")
|
core.chat_send_all("This is a chat message to all players")
|
||||||
```
|
```
|
||||||
|
|
||||||
Here is an example of how this appears in-game:
|
Here is an example of how this appears in-game:
|
||||||
@ -63,7 +63,7 @@ The message appears on a separate line to distinguish it from in-game player cha
|
|||||||
To send a message to a specific player, call the `chat_send_player` function:
|
To send a message to a specific player, call the `chat_send_player` function:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.chat_send_player("player1", "This is a chat message for player1")
|
core.chat_send_player("player1", "This is a chat message for player1")
|
||||||
```
|
```
|
||||||
|
|
||||||
This message displays in the same manner as messages to all players, but is
|
This message displays in the same manner as messages to all players, but is
|
||||||
@ -74,7 +74,7 @@ only visible to the named player, in this case, player1.
|
|||||||
To register a chat command, for example `/foo`, use `register_chatcommand`:
|
To register a chat command, for example `/foo`, use `register_chatcommand`:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_chatcommand("foo", {
|
core.register_chatcommand("foo", {
|
||||||
privs = {
|
privs = {
|
||||||
interact = true,
|
interact = true,
|
||||||
},
|
},
|
||||||
@ -166,7 +166,7 @@ or the [PIL documentation](https://www.lua.org/pil/20.2.html).
|
|||||||
To intercept a message, use register_on_chat_message:
|
To intercept a message, use register_on_chat_message:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_chat_message(function(name, message)
|
core.register_on_chat_message(function(name, message)
|
||||||
print(name .. " said " .. message)
|
print(name .. " said " .. message)
|
||||||
return false
|
return false
|
||||||
end)
|
end)
|
||||||
@ -182,10 +182,10 @@ You should make sure you take into account that it may be a chat command,
|
|||||||
or the user may not have `shout`.
|
or the user may not have `shout`.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_chat_message(function(name, message)
|
core.register_on_chat_message(function(name, message)
|
||||||
if message:sub(1, 1) == "/" then
|
if message:sub(1, 1) == "/" then
|
||||||
print(name .. " ran chat command")
|
print(name .. " ran chat command")
|
||||||
elseif minetest.check_player_privs(name, { shout = true }) then
|
elseif core.check_player_privs(name, { shout = true }) then
|
||||||
print(name .. " said " .. message)
|
print(name .. " said " .. message)
|
||||||
else
|
else
|
||||||
print(name .. " tried to say " .. message ..
|
print(name .. " tried to say " .. message ..
|
||||||
|
@ -146,7 +146,7 @@ function guessing.get_formspec(name)
|
|||||||
local formspec = {
|
local formspec = {
|
||||||
"formspec_version[4]",
|
"formspec_version[4]",
|
||||||
"size[6,3.476]",
|
"size[6,3.476]",
|
||||||
"label[0.375,0.5;", minetest.formspec_escape(text), "]",
|
"label[0.375,0.5;", core.formspec_escape(text), "]",
|
||||||
"field[0.375,1.25;5.25,0.8;number;Number;]",
|
"field[0.375,1.25;5.25,0.8;number;Number;]",
|
||||||
"button[1.5,2.3;3,0.8;guess;Guess]"
|
"button[1.5,2.3;3,0.8;guess;Guess]"
|
||||||
}
|
}
|
||||||
@ -166,10 +166,10 @@ is using `show_formspec`:
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
function guessing.show_to(name)
|
function guessing.show_to(name)
|
||||||
minetest.show_formspec(name, "guessing:game", guessing.get_formspec(name))
|
core.show_formspec(name, "guessing:game", guessing.get_formspec(name))
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_chatcommand("game", {
|
core.register_chatcommand("game", {
|
||||||
func = function(name)
|
func = function(name)
|
||||||
guessing.show_to(name)
|
guessing.show_to(name)
|
||||||
end,
|
end,
|
||||||
@ -206,19 +206,19 @@ The method for this is called formspec field submission, and for `show_formspec`
|
|||||||
submission is received using a global callback:
|
submission is received using a global callback:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
core.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
if formname ~= "guessing:game" then
|
if formname ~= "guessing:game" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields.guess then
|
if fields.guess then
|
||||||
local pname = player:get_player_name()
|
local pname = player:get_player_name()
|
||||||
minetest.chat_send_all(pname .. " guessed " .. fields.number)
|
core.chat_send_all(pname .. " guessed " .. fields.number)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
The function given in `minetest.register_on_player_receive_fields` is called
|
The function given in `core.register_on_player_receive_fields` is called
|
||||||
every time a user submits a form. Most callbacks will need to check the formname given
|
every time a user submits a form. Most callbacks will need to check the formname given
|
||||||
to the function, and exit if it is not the right form; however, some callbacks
|
to the function, and exit if it is not the right form; however, some callbacks
|
||||||
may need to work on multiple forms, or on all forms.
|
may need to work on multiple forms, or on all forms.
|
||||||
@ -239,7 +239,7 @@ the formspec based on guesses. The way to do this is using a concept called
|
|||||||
|
|
||||||
### Contexts
|
### Contexts
|
||||||
|
|
||||||
In many cases you want minetest.show_formspec to give information
|
In many cases you want core.show_formspec to give information
|
||||||
to the callback which you don't want to send to the client. This might include
|
to the callback which you don't want to send to the client. This might include
|
||||||
what a chat command was called with, or what the dialog is about. In this case,
|
what a chat command was called with, or what the dialog is about. In this case,
|
||||||
the target value that needs to be remembered.
|
the target value that needs to be remembered.
|
||||||
@ -255,7 +255,7 @@ local function get_context(name)
|
|||||||
return context
|
return context
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_leaveplayer(function(player)
|
core.register_on_leaveplayer(function(player)
|
||||||
_contexts[player:get_player_name()] = nil
|
_contexts[player:get_player_name()] = nil
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
@ -269,7 +269,7 @@ function guessing.show_to(name)
|
|||||||
context.target = context.target or math.random(1, 10)
|
context.target = context.target or math.random(1, 10)
|
||||||
|
|
||||||
local fs = guessing.get_formspec(name, context)
|
local fs = guessing.get_formspec(name, context)
|
||||||
minetest.show_formspec(name, "guessing:game", fs)
|
core.show_formspec(name, "guessing:game", fs)
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -318,13 +318,13 @@ There are three different ways that a formspec can be delivered to the client:
|
|||||||
|
|
||||||
### Node Meta Formspecs
|
### Node Meta Formspecs
|
||||||
|
|
||||||
`minetest.show_formspec` is not the only way to show a formspec; you can also
|
`core.show_formspec` is not the only way to show a formspec; you can also
|
||||||
add formspecs to a [node's metadata](../map/storage.html). For example,
|
add formspecs to a [node's metadata](../map/storage.html). For example,
|
||||||
this is used with chests to allow for faster opening times -
|
this is used with chests to allow for faster opening times -
|
||||||
you don't need to wait for the server to send the player the chest formspec.
|
you don't need to wait for the server to send the player the chest formspec.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("mymod:rightclick", {
|
core.register_node("mymod:rightclick", {
|
||||||
description = "Rightclick me!",
|
description = "Rightclick me!",
|
||||||
tiles = {"mymod_rightclick.png"},
|
tiles = {"mymod_rightclick.png"},
|
||||||
groups = {cracky = 1},
|
groups = {cracky = 1},
|
||||||
@ -333,7 +333,7 @@ minetest.register_node("mymod:rightclick", {
|
|||||||
-- The following code sets the formspec for chest.
|
-- The following code sets the formspec for chest.
|
||||||
-- Meta is a way of storing data onto a node.
|
-- Meta is a way of storing data onto a node.
|
||||||
|
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = core.get_meta(pos)
|
||||||
meta:set_string("formspec",
|
meta:set_string("formspec",
|
||||||
"formspec_version[4]" ..
|
"formspec_version[4]" ..
|
||||||
"size[5,5]" ..
|
"size[5,5]" ..
|
||||||
@ -355,7 +355,7 @@ receive form input for meta formspecs, you must include an
|
|||||||
`on_receive_fields` entry when registering the node.
|
`on_receive_fields` entry when registering the node.
|
||||||
|
|
||||||
This style of callback triggers when you press enter
|
This style of callback triggers when you press enter
|
||||||
in a field, which is impossible with `minetest.show_formspec`;
|
in a field, which is impossible with `core.show_formspec`;
|
||||||
however, this kind of form can only be shown by right-clicking on a
|
however, this kind of form can only be shown by right-clicking on a
|
||||||
node. It cannot be triggered programmatically.
|
node. It cannot be triggered programmatically.
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ to the right of the window, but to resize without breaking.
|
|||||||
You can create a HUD element once you have a copy of the player object:
|
You can create a HUD element once you have a copy of the player object:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local player = minetest.get_player_by_name("username")
|
local player = core.get_player_by_name("username")
|
||||||
local idx = player:hud_add({
|
local idx = player:hud_add({
|
||||||
hud_elem_type = "text",
|
hud_elem_type = "text",
|
||||||
position = {x = 0.5, y = 0.5},
|
position = {x = 0.5, y = 0.5},
|
||||||
@ -281,9 +281,9 @@ function score.update_hud(player)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_joinplayer(score.update_hud)
|
core.register_on_joinplayer(score.update_hud)
|
||||||
|
|
||||||
minetest.register_on_leaveplayer(function(player)
|
core.register_on_leaveplayer(function(player)
|
||||||
saved_huds[player:get_player_name()] = nil
|
saved_huds[player:get_player_name()] = nil
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
@ -28,9 +28,9 @@ Here is an example of how to add an antigravity command, which
|
|||||||
puts the caller in low G:
|
puts the caller in low G:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_chatcommand("antigravity", {
|
core.register_chatcommand("antigravity", {
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
local player = minetest.get_player_by_name(name)
|
local player = core.get_player_by_name(name)
|
||||||
player:set_physics_override({
|
player:set_physics_override({
|
||||||
gravity = 0.1, -- set gravity to 10% of its original value
|
gravity = 0.1, -- set gravity to 10% of its original value
|
||||||
-- (0.1 * 9.81)
|
-- (0.1 * 9.81)
|
||||||
|
@ -48,7 +48,7 @@ Privileges are **not** for indicating class or status.
|
|||||||
Use `register_privilege` to declare a new privilege:
|
Use `register_privilege` to declare a new privilege:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_privilege("vote", {
|
core.register_privilege("vote", {
|
||||||
description = "Can vote on issues",
|
description = "Can vote on issues",
|
||||||
give_to_singleplayer = true
|
give_to_singleplayer = true
|
||||||
})
|
})
|
||||||
@ -62,7 +62,7 @@ actually needed in the above definition.
|
|||||||
To quickly check whether a player has all the required privileges:
|
To quickly check whether a player has all the required privileges:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local has, missing = minetest.check_player_privs(player_or_name, {
|
local has, missing = core.check_player_privs(player_or_name, {
|
||||||
interact = true,
|
interact = true,
|
||||||
vote = true })
|
vote = true })
|
||||||
```
|
```
|
||||||
@ -72,7 +72,7 @@ If `has` is false, then `missing` will contain a key-value table
|
|||||||
of the missing privileges.
|
of the missing privileges.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local has, missing = minetest.check_player_privs(name, {
|
local has, missing = core.check_player_privs(name, {
|
||||||
interact = true,
|
interact = true,
|
||||||
vote = true })
|
vote = true })
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ If you don't need to check the missing privileges, you can put
|
|||||||
`check_player_privs` directly into the if statement.
|
`check_player_privs` directly into the if statement.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
if not minetest.check_player_privs(name, { interact=true }) then
|
if not core.check_player_privs(name, { interact=true }) then
|
||||||
return false, "You need interact for this!"
|
return false, "You need interact for this!"
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
@ -99,11 +99,11 @@ being online.
|
|||||||
|
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local privs = minetest.get_player_privs(name)
|
local privs = core.get_player_privs(name)
|
||||||
print(dump(privs))
|
print(dump(privs))
|
||||||
|
|
||||||
privs.vote = true
|
privs.vote = true
|
||||||
minetest.set_player_privs(name, privs)
|
core.set_player_privs(name, privs)
|
||||||
```
|
```
|
||||||
|
|
||||||
Privileges are always specified as a key-value table with the key being
|
Privileges are always specified as a key-value table with the key being
|
||||||
|
@ -100,7 +100,7 @@ what is listening to something.
|
|||||||
|
|
||||||
In the next chapter, we will discuss how to automatically test your
|
In the next chapter, we will discuss how to automatically test your
|
||||||
code and one of the problems we will have is how to separate your logic
|
code and one of the problems we will have is how to separate your logic
|
||||||
(calculations, what should be done) from API calls (`minetest.*`, other mods)
|
(calculations, what should be done) from API calls (`core.*`, other mods)
|
||||||
as much as possible.
|
as much as possible.
|
||||||
|
|
||||||
One way to do this is to think about:
|
One way to do this is to think about:
|
||||||
@ -173,14 +173,14 @@ function land.show_create_formspec(name)
|
|||||||
]]
|
]]
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_chatcommand("/land", {
|
core.register_chatcommand("/land", {
|
||||||
privs = { land = true },
|
privs = { land = true },
|
||||||
func = function(name)
|
func = function(name)
|
||||||
land.handle_creation_request(name)
|
land.handle_creation_request(name)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_on_player_receive_fields(function(player,
|
core.register_on_player_receive_fields(function(player,
|
||||||
formname, fields)
|
formname, fields)
|
||||||
land.handle_create_submit(player:get_player_name(),
|
land.handle_create_submit(player:get_player_name(),
|
||||||
fields.area_name)
|
fields.area_name)
|
||||||
@ -227,7 +227,7 @@ this isn't the real world. A good compromise is to reduce the mod into two
|
|||||||
parts:
|
parts:
|
||||||
|
|
||||||
* **API** - This was the model and controller above. There should be no uses of
|
* **API** - This was the model and controller above. There should be no uses of
|
||||||
`minetest.` here.
|
`core.` here.
|
||||||
* **View** - This was also the view above. It's a good idea to structure this into separate
|
* **View** - This was also the view above. It's a good idea to structure this into separate
|
||||||
files for each type of event.
|
files for each type of event.
|
||||||
|
|
||||||
|
@ -43,11 +43,11 @@ give themselves moderator privileges:
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
local function show_formspec(name)
|
local function show_formspec(name)
|
||||||
if not minetest.check_player_privs(name, { privs = true }) then
|
if not core.check_player_privs(name, { privs = true }) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.show_formspec(name, "modman:modman", [[
|
core.show_formspec(name, "modman:modman", [[
|
||||||
size[3,2]
|
size[3,2]
|
||||||
field[0,0;3,1;target;Name;]
|
field[0,0;3,1;target;Name;]
|
||||||
button_exit[0,1;3,1;sub;Promote]
|
button_exit[0,1;3,1;sub;Promote]
|
||||||
@ -55,14 +55,14 @@ local function show_formspec(name)
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_on_player_receive_fields(function(player,
|
core.register_on_player_receive_fields(function(player,
|
||||||
formname, fields)
|
formname, fields)
|
||||||
-- BAD! Missing privilege check here!
|
-- BAD! Missing privilege check here!
|
||||||
|
|
||||||
local privs = minetest.get_player_privs(fields.target)
|
local privs = core.get_player_privs(fields.target)
|
||||||
privs.kick = true
|
privs.kick = true
|
||||||
privs.ban = true
|
privs.ban = true
|
||||||
minetest.set_player_privs(fields.target, privs)
|
core.set_player_privs(fields.target, privs)
|
||||||
return true
|
return true
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
@ -70,9 +70,9 @@ end)
|
|||||||
Add a privilege check to solve this:
|
Add a privilege check to solve this:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_player_receive_fields(function(player,
|
core.register_on_player_receive_fields(function(player,
|
||||||
formname, fields)
|
formname, fields)
|
||||||
if not minetest.check_player_privs(name, { privs = true }) then
|
if not core.check_player_privs(name, { privs = true }) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ are given will change it for the caller too, and any subsequent callbacks. Howev
|
|||||||
it will only be saved in the engine if the callback caller sets it.
|
it will only be saved in the engine if the callback caller sets it.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_item_eat(function(hp_change, replace_with_item,
|
core.register_on_item_eat(function(hp_change, replace_with_item,
|
||||||
itemstack, user, pointed_thing)
|
itemstack, user, pointed_thing)
|
||||||
itemstack:get_meta():set_string("description", "Partially eaten")
|
itemstack:get_meta():set_string("description", "Partially eaten")
|
||||||
-- Almost correct! Data will be lost if another
|
-- Almost correct! Data will be lost if another
|
||||||
@ -125,7 +125,7 @@ but if a callback does cancel this, then the update may be lost.
|
|||||||
It's better to do this instead:
|
It's better to do this instead:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_item_eat(function(hp_change, replace_with_item,
|
core.register_on_item_eat(function(hp_change, replace_with_item,
|
||||||
itemstack, user, pointed_thing)
|
itemstack, user, pointed_thing)
|
||||||
itemstack:get_meta():set_string("description", "Partially eaten")
|
itemstack:get_meta():set_string("description", "Partially eaten")
|
||||||
user:get_inventory():set_stack("main", user:get_wield_index(),
|
user:get_inventory():set_stack("main", user:get_wield_index(),
|
||||||
|
@ -19,7 +19,6 @@ After you've read this book, take a look at the following.
|
|||||||
### Lua Programming
|
### Lua Programming
|
||||||
|
|
||||||
* [Programming in Lua (PIL)](http://www.lua.org/pil/).
|
* [Programming in Lua (PIL)](http://www.lua.org/pil/).
|
||||||
* [Lua Crash Course](http://luatut.com/crash_course.html).
|
|
||||||
|
|
||||||
### 3D Modelling
|
### 3D Modelling
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ Any users can submit almost any formspec with any values at any time.
|
|||||||
Here's some real code found in a mod:
|
Here's some real code found in a mod:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_player_receive_fields(function(player,
|
core.register_on_player_receive_fields(function(player,
|
||||||
formname, fields)
|
formname, fields)
|
||||||
for key, field in pairs(fields) do
|
for key, field in pairs(fields) do
|
||||||
local x,y,z = string.match(key,
|
local x,y,z = string.match(key,
|
||||||
@ -87,7 +87,7 @@ to the full Lua API.
|
|||||||
Can you spot the vulnerability in the following?
|
Can you spot the vulnerability in the following?
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local ie = minetest.request_insecure_environment()
|
local ie = core.request_insecure_environment()
|
||||||
ie.os.execute(("path/to/prog %d"):format(3))
|
ie.os.execute(("path/to/prog %d"):format(3))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -57,12 +57,12 @@ control characters in text, telling Minetest where and how to translate
|
|||||||
text. This is referred to as marked up text, and will be discussed more later.
|
text. This is referred to as marked up text, and will be discussed more later.
|
||||||
|
|
||||||
To mark text as translatable, use a translator function (`S()`), obtained using
|
To mark text as translatable, use a translator function (`S()`), obtained using
|
||||||
`minetest.get_translator(textdomain)`:
|
`core.get_translator(textdomain)`:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local S = minetest.get_translator("mymod")
|
local S = core.get_translator("mymod")
|
||||||
|
|
||||||
minetest.register_craftitem("mymod:item", {
|
core.register_craftitem("mymod:item", {
|
||||||
description = S("My Item"),
|
description = S("My Item"),
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@ -75,7 +75,7 @@ avoid mod conflicts.
|
|||||||
|
|
||||||
Marked up text can be used in most places where human-readable text is accepted,
|
Marked up text can be used in most places where human-readable text is accepted,
|
||||||
including formspecs, item def fields, infotext, and more. When including marked
|
including formspecs, item def fields, infotext, and more. When including marked
|
||||||
text in formspecs, you need to escape the text using `minetest.formspec_escape`.
|
text in formspecs, you need to escape the text using `core.formspec_escape`.
|
||||||
|
|
||||||
When the client encounters translatable text, such as that passed to
|
When the client encounters translatable text, such as that passed to
|
||||||
`description`, it looks it up in the player's language's translation file. If a
|
`description`, it looks it up in the player's language's translation file. If a
|
||||||
@ -85,7 +85,7 @@ Translatable marked up text contains the English source text, the textdomain,
|
|||||||
and any additional arguments passed to `S()`. It's essentially a text encoding
|
and any additional arguments passed to `S()`. It's essentially a text encoding
|
||||||
of the `S` call, containing all the required information.
|
of the `S` call, containing all the required information.
|
||||||
|
|
||||||
Another type of marked up text is that returned by `minetest.colorize`.
|
Another type of marked up text is that returned by `core.colorize`.
|
||||||
|
|
||||||
{% include notice.html notice=page.marked_text_encoding %}
|
{% include notice.html notice=page.marked_text_encoding %}
|
||||||
|
|
||||||
@ -127,8 +127,8 @@ translators from changing the order of variables within a sentence. Instead,
|
|||||||
you should use the translation system's format/arguments system:
|
you should use the translation system's format/arguments system:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_joinplayer(function(player)
|
core.register_on_joinplayer(function(player)
|
||||||
minetest.chat_send_all(S("Everyone, say hi to @1!", player:get_player_name()))
|
core.chat_send_all(S("Everyone, say hi to @1!", player:get_player_name()))
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -172,13 +172,13 @@ local list = {
|
|||||||
S("Potato")
|
S("Potato")
|
||||||
}
|
}
|
||||||
|
|
||||||
minetest.register_chatcommand("find", {
|
core.register_chatcommand("find", {
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
local info = minetest.get_player_information(name)
|
local info = core.get_player_information(name)
|
||||||
local language = info and info.language or "en"
|
local language = info and info.language or "en"
|
||||||
|
|
||||||
for _, line in ipairs(list) do
|
for _, line in ipairs(list) do
|
||||||
local trans = minetest.get_translated_string(language, line)
|
local trans = core.get_translated_string(language, line)
|
||||||
if trans:contains(query) then
|
if trans:contains(query) then
|
||||||
return line
|
return line
|
||||||
end
|
end
|
||||||
|
@ -54,7 +54,7 @@ names ending in `_spec`, and then executes them in a standalone Lua environment.
|
|||||||
```lua
|
```lua
|
||||||
mymod = {}
|
mymod = {}
|
||||||
|
|
||||||
dofile(minetest.get_modpath("mymod") .. "/api.lua")
|
dofile(core.get_modpath("mymod") .. "/api.lua")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ _G.minetest = {}
|
|||||||
|
|
||||||
-- Define the mock function
|
-- Define the mock function
|
||||||
local chat_send_all_calls = {}
|
local chat_send_all_calls = {}
|
||||||
function minetest.chat_send_all(name, message)
|
function core.chat_send_all(name, message)
|
||||||
table.insert(chat_send_all_calls, { name = name, message = message })
|
table.insert(chat_send_all_calls, { name = name, message = message })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ Oltre che farli a mano, per creare dei diagrammi di Voronoi si possono usare pro
|
|||||||
Il seguente codice registra un semplice bioma chiamato "distesa_erbosa":
|
Il seguente codice registra un semplice bioma chiamato "distesa_erbosa":
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_biome({
|
core.register_biome({
|
||||||
name = "distesa_erbosa",
|
name = "distesa_erbosa",
|
||||||
node_top = "default:dirt_with_grass",
|
node_top = "default:dirt_with_grass",
|
||||||
depth_top = 1,
|
depth_top = 1,
|
||||||
@ -144,7 +144,7 @@ Ricordati che devi specificare il nodo che vuoi usare in quanto decorazione, i d
|
|||||||
Per esempio:
|
Per esempio:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_decoration({
|
core.register_decoration({
|
||||||
deco_type = "simple",
|
deco_type = "simple",
|
||||||
place_on = {"base:dirt_with_grass"},
|
place_on = {"base:dirt_with_grass"},
|
||||||
sidelen = 16,
|
sidelen = 16,
|
||||||
@ -167,7 +167,7 @@ Le schematic sono molto simili alle decorazioni semplici, solo che piazzano più
|
|||||||
Per esempio:
|
Per esempio:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_decoration({
|
core.register_decoration({
|
||||||
deco_type = "schematic",
|
deco_type = "schematic",
|
||||||
place_on = {"base:desert_sand"},
|
place_on = {"base:desert_sand"},
|
||||||
sidelen = 16,
|
sidelen = 16,
|
||||||
@ -175,7 +175,7 @@ minetest.register_decoration({
|
|||||||
biomes = {"desert"},
|
biomes = {"desert"},
|
||||||
y_max = 200,
|
y_max = 200,
|
||||||
y_min = 1,
|
y_min = 1,
|
||||||
schematic = minetest.get_modpath("plants") .. "/schematics/cactus.mts",
|
schematic = core.get_modpath("plants") .. "/schematics/cactus.mts",
|
||||||
flags = "place_center_x, place_center_z",
|
flags = "place_center_x, place_center_z",
|
||||||
rotation = "random",
|
rotation = "random",
|
||||||
})
|
})
|
||||||
@ -195,7 +195,7 @@ I giochi disponibili dovrebbero già includere un alias del generatore mappa (*m
|
|||||||
Gli alias del generatore mappa forniscono informazioni al generatore principale, e possono essere registrati secondo lo schema:
|
Gli alias del generatore mappa forniscono informazioni al generatore principale, e possono essere registrati secondo lo schema:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_alias("mapgen_stone", "base:smoke_stone")
|
core.register_alias("mapgen_stone", "base:smoke_stone")
|
||||||
```
|
```
|
||||||
|
|
||||||
Almeno almeno dovresti registrare:
|
Almeno almeno dovresti registrare:
|
||||||
|
@ -10,8 +10,8 @@ redirect_from:
|
|||||||
mapgen_object:
|
mapgen_object:
|
||||||
level: warning
|
level: warning
|
||||||
title: LVM e generatore mappa
|
title: LVM e generatore mappa
|
||||||
message: Non usare `minetest.get_voxel_manip()` con il generatore mappa, in quanto può causare glitch.
|
message: Non usare `core.get_voxel_manip()` con il generatore mappa, in quanto può causare glitch.
|
||||||
Usa invece `minetest.get_mapgen_object("voxelmanip")`.
|
Usa invece `core.get_mapgen_object("voxelmanip")`.
|
||||||
---
|
---
|
||||||
|
|
||||||
## Introduzione <!-- omit in toc -->
|
## Introduzione <!-- omit in toc -->
|
||||||
@ -39,7 +39,7 @@ Si possono caricare solamente aree cubiche negli LVM, quindi devi capire da te q
|
|||||||
Fatto ciò, puoi creare l'LVM:
|
Fatto ciò, puoi creare l'LVM:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local vm = minetest.get_voxel_manip()
|
local vm = core.get_voxel_manip()
|
||||||
local emin, emax = vm:read_from_map(pos1, pos2)
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ Per scoprire qual è l'ID assegnato a un tipo di nodo, si usa `get_content_id()`
|
|||||||
Per esempio:
|
Per esempio:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local c_pietra = minetest.get_content_id("default:stone")
|
local c_pietra = core.get_content_id("default:stone")
|
||||||
```
|
```
|
||||||
|
|
||||||
Si può ora controllare se un nodo è effettivamente di pietra:
|
Si può ora controllare se un nodo è effettivamente di pietra:
|
||||||
@ -143,16 +143,16 @@ vm:write_to_map(true)
|
|||||||
Per la luce e param2, invece si usano `set_light_data()` e `set_param2_data()`.
|
Per la luce e param2, invece si usano `set_light_data()` e `set_param2_data()`.
|
||||||
|
|
||||||
`write_to_map()` richiede un booleano che è `true` se si vuole che venga calcolata anche la luce.
|
`write_to_map()` richiede un booleano che è `true` se si vuole che venga calcolata anche la luce.
|
||||||
Se si passa `false` invece, ci sarà bisogno di ricalcolarla in un secondo tempo usando `minetest.fix_light`.
|
Se si passa `false` invece, ci sarà bisogno di ricalcolarla in un secondo tempo usando `core.fix_light`.
|
||||||
|
|
||||||
## Esempio
|
## Esempio
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local function da_erba_a_terra(pos1, pos2)
|
local function da_erba_a_terra(pos1, pos2)
|
||||||
local c_terra = minetest.get_content_id("default:dirt")
|
local c_terra = core.get_content_id("default:dirt")
|
||||||
local c_erba = minetest.get_content_id("default:dirt_with_grass")
|
local c_erba = core.get_content_id("default:dirt_with_grass")
|
||||||
-- legge i dati nella LVM
|
-- legge i dati nella LVM
|
||||||
local vm = minetest.get_voxel_manip()
|
local vm = core.get_voxel_manip()
|
||||||
local emin, emax = vm:read_from_map(pos1, pos2)
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
||||||
local a = VoxelArea:new{
|
local a = VoxelArea:new{
|
||||||
MinEdge = emin,
|
MinEdge = emin,
|
||||||
|
@ -150,7 +150,7 @@ Segue un esempio che mette insieme tutto ciò discusso finora:
|
|||||||
```lua
|
```lua
|
||||||
print("Questo file parte all'avvio!")
|
print("Questo file parte all'avvio!")
|
||||||
|
|
||||||
minetest.register_node("lamiamod:nodo", {
|
core.register_node("lamiamod:nodo", {
|
||||||
description = "Questo è un nodo",
|
description = "Questo è un nodo",
|
||||||
tiles = {"lamiamod_nodo.png"},
|
tiles = {"lamiamod_nodo.png"},
|
||||||
groups = {cracky = 1}
|
groups = {cracky = 1}
|
||||||
|
@ -159,7 +159,7 @@ mymod.foo("foobar")
|
|||||||
Il metodo consigliato per includere in una mod altri script Lua è usare *dofile*.
|
Il metodo consigliato per includere in una mod altri script Lua è usare *dofile*.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
dofile(minetest.get_modpath("modname") .. "/script.lua")
|
dofile(core.get_modpath("modname") .. "/script.lua")
|
||||||
```
|
```
|
||||||
|
|
||||||
Uno script può ritornare un valore, che è utile per condividere variabili locali private:
|
Uno script può ritornare un valore, che è utile per condividere variabili locali private:
|
||||||
@ -169,7 +169,7 @@ Uno script può ritornare un valore, che è utile per condividere variabili loca
|
|||||||
return "Hello world!"
|
return "Hello world!"
|
||||||
|
|
||||||
-- init.lua
|
-- init.lua
|
||||||
local ret = dofile(minetest.get_modpath("modname") .. "/script.lua")
|
local ret = dofile(core.get_modpath("modname") .. "/script.lua")
|
||||||
print(ret) -- Hello world!
|
print(ret) -- Hello world!
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ description: Scopri i richiami, le azioni e gli eventi, come on_use, on_punch, o
|
|||||||
|
|
||||||
Minetest usa una struttura di moddaggio estensivamente incentrata sui richiami. Un richiamo è una funzione che si dà a un'API e che viene chiamata quando l'evento registrato si verifica.
|
Minetest usa una struttura di moddaggio estensivamente incentrata sui richiami. Un richiamo è una funzione che si dà a un'API e che viene chiamata quando l'evento registrato si verifica.
|
||||||
Per esempio, puoi aggiungere una funzione `on_punch` nella definizione di un nodo, che verrà chiamata quando questo viene colpito.
|
Per esempio, puoi aggiungere una funzione `on_punch` nella definizione di un nodo, che verrà chiamata quando questo viene colpito.
|
||||||
Ci sono poi anche dei richiami globali, come `minetest.register_on_punchnode`, che in questo caso verrà invocato al colpire qualsiasi nodo.
|
Ci sono poi anche dei richiami globali, come `core.register_on_punchnode`, che in questo caso verrà invocato al colpire qualsiasi nodo.
|
||||||
|
|
||||||
- [Richiami degli oggetti](#richiami-degli-oggetti)
|
- [Richiami degli oggetti](#richiami-degli-oggetti)
|
||||||
- [on_use](#on_use)
|
- [on_use](#on_use)
|
||||||
@ -31,9 +31,9 @@ Quando un giocatore ha un nodo, un oggetto fabbricabile o uno strumento nel prop
|
|||||||
| Richiamo | Assegnazione base | Valore base |
|
| Richiamo | Assegnazione base | Valore base |
|
||||||
|------------------|---------------------------|----------------------------------------------|
|
|------------------|---------------------------|----------------------------------------------|
|
||||||
| on_use | clic sinistro | nil |
|
| on_use | clic sinistro | nil |
|
||||||
| on_place | clic destro su un nodo | `minetest.item_place` |
|
| on_place | clic destro su un nodo | `core.item_place` |
|
||||||
| on_secondary_use | clic destro a vuoto | `minetest.item_secondary_use` (non fa nulla) |
|
| on_secondary_use | clic destro a vuoto | `core.item_secondary_use` (non fa nulla) |
|
||||||
| on_drop | Q | `minetest.item_drop` |
|
| on_drop | Q | `core.item_drop` |
|
||||||
| after_use | allo scavare un nodo | nil |
|
| after_use | allo scavare un nodo | nil |
|
||||||
|
|
||||||
|
|
||||||
@ -43,26 +43,26 @@ Sovrascrivere l'uso dell'oggetto impedisce che quest'ultimo possa essere usato p
|
|||||||
Un impiego comune di questo richiamo lo si trova nel cibo:
|
Un impiego comune di questo richiamo lo si trova nel cibo:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craftitem("miamod:fangotorta", {
|
core.register_craftitem("miamod:fangotorta", {
|
||||||
description = "Torta aliena di fango",
|
description = "Torta aliena di fango",
|
||||||
inventory_image = "miamod_fangotorta.png",
|
inventory_image = "miamod_fangotorta.png",
|
||||||
on_use = minetest.item_eat(20),
|
on_use = core.item_eat(20),
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Il numero fornito alla funzione minetest.item_eat è il numero di punti salute ripristinati al consumare il cibo.
|
Il numero fornito alla funzione core.item_eat è il numero di punti salute ripristinati al consumare il cibo.
|
||||||
In gioco ogni cuore equivale a due punti.
|
In gioco ogni cuore equivale a due punti.
|
||||||
Un giocatore ha solitamente un massimo di 10 cuori, ovvero 20 punti salute, e quest'ultimi non devono per forza essere interi - bensì anche decimali.
|
Un giocatore ha solitamente un massimo di 10 cuori, ovvero 20 punti salute, e quest'ultimi non devono per forza essere interi - bensì anche decimali.
|
||||||
|
|
||||||
`minetest.item_eat()` è una funzione che ritorna un'altra funzione, in questo caso quindi impostandola come richiamo di on_use.
|
`core.item_eat()` è una funzione che ritorna un'altra funzione, in questo caso quindi impostandola come richiamo di on_use.
|
||||||
Ciò significa che il codice in alto è alquanto simile al seguente:
|
Ciò significa che il codice in alto è alquanto simile al seguente:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craftitem("miamod:fangotorta", {
|
core.register_craftitem("miamod:fangotorta", {
|
||||||
description = "Torta aliena di fango",
|
description = "Torta aliena di fango",
|
||||||
inventory_image = "miamod_fangotorta.png",
|
inventory_image = "miamod_fangotorta.png",
|
||||||
on_use = function(...)
|
on_use = function(...)
|
||||||
return minetest.do_item_eat(20, nil, ...)
|
return core.do_item_eat(20, nil, ...)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@ -76,13 +76,13 @@ come per esempio riprodurre un suono personalizzato.
|
|||||||
La differenza tra `on_place` e `on_secondary_use` consiste nel fatto che `on_place` viene chiamato quando il giocatore sta puntando un nodo, mentre `on_secondary_use` quando non ne punta uno.
|
La differenza tra `on_place` e `on_secondary_use` consiste nel fatto che `on_place` viene chiamato quando il giocatore sta puntando un nodo, mentre `on_secondary_use` quando non ne punta uno.
|
||||||
|
|
||||||
Entrambi i richiami sono invocati per tutti i tipi di oggetti.
|
Entrambi i richiami sono invocati per tutti i tipi di oggetti.
|
||||||
`on_place` risponde alla funzione `minetest.item_place`, la quale o gestisce la chiamata a `on_rightclick` del nodo puntato, o piazza l'oggetto in mano se questo è un nodo.
|
`on_place` risponde alla funzione `core.item_place`, la quale o gestisce la chiamata a `on_rightclick` del nodo puntato, o piazza l'oggetto in mano se questo è un nodo.
|
||||||
|
|
||||||
|
|
||||||
### on_drop
|
### on_drop
|
||||||
|
|
||||||
`on_drop` viene chiamato quando il giocatore fa richiesta per buttare un oggetto, per esempio usando il tasto apposito (Q) o trascinando l'oggetto fuori dall'inventario.
|
`on_drop` viene chiamato quando il giocatore fa richiesta per buttare un oggetto, per esempio usando il tasto apposito (Q) o trascinando l'oggetto fuori dall'inventario.
|
||||||
Risponde alla funzione `minetest.item_drop`, la quale gestisce il buttare l'oggetto.
|
Risponde alla funzione `core.item_drop`, la quale gestisce il buttare l'oggetto.
|
||||||
|
|
||||||
### after_use
|
### after_use
|
||||||
|
|
||||||
@ -100,18 +100,18 @@ end
|
|||||||
## item_place contro place_item
|
## item_place contro place_item
|
||||||
|
|
||||||
L'API di Minetest include varie implementazioni già pronte di richiami.
|
L'API di Minetest include varie implementazioni già pronte di richiami.
|
||||||
Queste seguono la nomenclatura "tipodioggetto_azione", per esempio `minetest.item_place` e `minetest.node_dig`.
|
Queste seguono la nomenclatura "tipodioggetto_azione", per esempio `core.item_place` e `core.node_dig`.
|
||||||
Alcune sono usate direttamente, mentre altre sono funzioni che ritornano il richiamo vero e proprio:
|
Alcune sono usate direttamente, mentre altre sono funzioni che ritornano il richiamo vero e proprio:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_item("miamod:esempio", {
|
core.register_item("miamod:esempio", {
|
||||||
on_place = minetest.item_place,
|
on_place = core.item_place,
|
||||||
on_use = minetest.item_eat(10),
|
on_use = core.item_eat(10),
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Inoltre, l'API di Minetest include funzioni già pronte che _fanno_ qualcosa.
|
Inoltre, l'API di Minetest include funzioni già pronte che _fanno_ qualcosa.
|
||||||
Queste sono spesso chiamate con nomi che rischiano di farle confondere con le implementazioni dei richiami, tuttavia hanno un verbo all'inizio (per esempio `minetest.place_item` e `minetest.dig_node`, che permettono rispettivamente di scavare e piazzare nodi come se lo stesse facendo un giocatore).
|
Queste sono spesso chiamate con nomi che rischiano di farle confondere con le implementazioni dei richiami, tuttavia hanno un verbo all'inizio (per esempio `core.place_item` e `core.dig_node`, che permettono rispettivamente di scavare e piazzare nodi come se lo stesse facendo un giocatore).
|
||||||
|
|
||||||
|
|
||||||
## Richiami dei nodi
|
## Richiami dei nodi
|
||||||
@ -128,9 +128,9 @@ Molti richiami dei nodi sono collegati alle operazioni effettuate - appunto - su
|
|||||||
### Tasto destro e nodi piazzati
|
### Tasto destro e nodi piazzati
|
||||||
|
|
||||||
Quando un utente preme col tasto destro un nodo mentre ha un oggetto in mano, viene invocato il richiamo `on_place` dell'oggetto.
|
Quando un utente preme col tasto destro un nodo mentre ha un oggetto in mano, viene invocato il richiamo `on_place` dell'oggetto.
|
||||||
Di base, questo è impostato a `minetest.item_place`.
|
Di base, questo è impostato a `core.item_place`.
|
||||||
Se il nodo puntato ha un richiamo `on_rightclick` e il tasto accovacciati (shift) è tenuto premuto, allora verrà chiamato `on_rightclick`.
|
Se il nodo puntato ha un richiamo `on_rightclick` e il tasto accovacciati (shift) è tenuto premuto, allora verrà chiamato `on_rightclick`.
|
||||||
Diversamente, `minetest.item_place` piazzerà il nodo.
|
Diversamente, `core.item_place` piazzerà il nodo.
|
||||||
|
|
||||||
Piazzare un nodo invocherà simultaneamente `on_construct` e `after_place_node`: il primo è chiamato da ogni evento che cambia i singoli nodi (quindi non in blocco) e ritorna la posizione e il valore del nodo.
|
Piazzare un nodo invocherà simultaneamente `on_construct` e `after_place_node`: il primo è chiamato da ogni evento che cambia i singoli nodi (quindi non in blocco) e ritorna la posizione e il valore del nodo.
|
||||||
`after_place_node` viene invece chiamato solamente al piazzare un nodo, contenendo di conseguenza più informazioni - come chi l'ha piazzato e l'ItemStack.
|
`after_place_node` viene invece chiamato solamente al piazzare un nodo, contenendo di conseguenza più informazioni - come chi l'ha piazzato e l'ItemStack.
|
||||||
@ -139,20 +139,20 @@ Piazzare un nodo invocherà simultaneamente `on_construct` e `after_place_node`:
|
|||||||
Per via di ciò, `place` potrebbe essere un giocatore, ma anche un'entità o `nil`.
|
Per via di ciò, `place` potrebbe essere un giocatore, ma anche un'entità o `nil`.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("miamod:mionodo", {
|
core.register_node("miamod:mionodo", {
|
||||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
if clicker:is_player() then
|
if clicker:is_player() then
|
||||||
minetest.chat_send_player(clicker:get_player_name(), "Ciao mondo!")
|
core.chat_send_player(clicker:get_player_name(), "Ciao mondo!")
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
on_construct = function(pos, node)
|
on_construct = function(pos, node)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = core.get_meta(pos)
|
||||||
meta:set_string("infotext", "Il mio nodo!")
|
meta:set_string("infotext", "Il mio nodo!")
|
||||||
end,
|
end,
|
||||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||||
-- controlla chi sta piazzando
|
-- controlla chi sta piazzando
|
||||||
if placer and placer:is_player() then
|
if placer and placer:is_player() then
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = core.get_meta(pos)
|
||||||
meta:set_string("proprietario", placer:get_player_name())
|
meta:set_string("proprietario", placer:get_player_name())
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
@ -166,14 +166,14 @@ Se l'oggetto in mano possiede un richiamo `on_use`, questo verrà chiamato.
|
|||||||
Diversamente, verrà chiamato il richiamo `on_punch` sul nodo selezionato.
|
Diversamente, verrà chiamato il richiamo `on_punch` sul nodo selezionato.
|
||||||
|
|
||||||
Quando il giocatore tenta di scavare un nodo, viene eseguito il richiamo `on_dig` del nodo.
|
Quando il giocatore tenta di scavare un nodo, viene eseguito il richiamo `on_dig` del nodo.
|
||||||
Di base, ciò equivale a `minetest.node_dig`, che controlla eventuali protezioni dell'area, usura l'oggetto, rimuove il nodo, e ne esegue il richiamo `after_dig_node`.
|
Di base, ciò equivale a `core.node_dig`, che controlla eventuali protezioni dell'area, usura l'oggetto, rimuove il nodo, e ne esegue il richiamo `after_dig_node`.
|
||||||
|
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("miamod:mionodo", {
|
core.register_node("miamod:mionodo", {
|
||||||
on_punch = function(pos, node, puncher, pointed_thing)
|
on_punch = function(pos, node, puncher, pointed_thing)
|
||||||
if puncher:is_player() then
|
if puncher:is_player() then
|
||||||
minetest.chat_send_player(puncher:get_player_name(), "Ahia!")
|
core.chat_send_player(puncher:get_player_name(), "Ahia!")
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
@ -90,7 +90,7 @@ Gli inventari collocati nei nodi sono associati alle coordinate di un nodo speci
|
|||||||
Il nodo deve essere stato caricato perché viene salvato [nei suoi metadati](../map/storage.html#metadata).
|
Il nodo deve essere stato caricato perché viene salvato [nei suoi metadati](../map/storage.html#metadata).
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local inv = minetest.get_inventory({ type="node", pos={x=1, y=2, z=3} })
|
local inv = core.get_inventory({ type="node", pos={x=1, y=2, z=3} })
|
||||||
```
|
```
|
||||||
|
|
||||||
L'esempio in alto ottiene il *riferimento a un inventario*, comunemente definito *InvRef*.
|
L'esempio in alto ottiene il *riferimento a un inventario*, comunemente definito *InvRef*.
|
||||||
@ -107,7 +107,7 @@ Gli inventari dei giocatori si ottengono in maniera simile, oppure usando il rif
|
|||||||
In entrambi casi, il giocatore deve essere connesso.
|
In entrambi casi, il giocatore deve essere connesso.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local inv = minetest.get_inventory({ type="player", name="player1" })
|
local inv = core.get_inventory({ type="player", name="player1" })
|
||||||
-- oppure
|
-- oppure
|
||||||
local inv = player:get_inventory()
|
local inv = player:get_inventory()
|
||||||
```
|
```
|
||||||
@ -115,14 +115,14 @@ local inv = player:get_inventory()
|
|||||||
Gli inventari separati, infine, sono quelli non collegati né a nodi né a giocatori, e al contrario degli altri, vengono persi dopo un riavvio.
|
Gli inventari separati, infine, sono quelli non collegati né a nodi né a giocatori, e al contrario degli altri, vengono persi dopo un riavvio.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local inv = minetest.get_inventory({
|
local inv = core.get_inventory({
|
||||||
type="detached", name="nome_inventario" })
|
type="detached", name="nome_inventario" })
|
||||||
```
|
```
|
||||||
|
|
||||||
Un'ulteriore differenza, è che gli inventari separati devono essere creati prima di poterci accedere:
|
Un'ulteriore differenza, è che gli inventari separati devono essere creati prima di poterci accedere:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.create_detached_inventory("inventory_name")
|
core.create_detached_inventory("inventory_name")
|
||||||
```
|
```
|
||||||
|
|
||||||
La funzione `create_detached_inventory` accetta 3 parametri, di cui solo il primo - il nome - è necessario.
|
La funzione `create_detached_inventory` accetta 3 parametri, di cui solo il primo - il nome - è necessario.
|
||||||
@ -130,7 +130,7 @@ Il secondo parametro prende una tabella di callback, che possono essere utilizza
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Input only detached inventory
|
-- Input only detached inventory
|
||||||
minetest.create_detached_inventory("inventory_name", {
|
core.create_detached_inventory("inventory_name", {
|
||||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||||
return count -- permette di spostare gli oggetti
|
return count -- permette di spostare gli oggetti
|
||||||
end,
|
end,
|
||||||
@ -144,9 +144,9 @@ minetest.create_detached_inventory("inventory_name", {
|
|||||||
end,
|
end,
|
||||||
|
|
||||||
on_put = function(inv, listname, index, stack, player)
|
on_put = function(inv, listname, index, stack, player)
|
||||||
minetest.chat_send_all(player:get_player_name() ..
|
core.chat_send_all(player:get_player_name() ..
|
||||||
" ha messo " .. stack:to_string() ..
|
" ha messo " .. stack:to_string() ..
|
||||||
" nella cassa delle donazioni da " .. minetest.pos_to_string(player:get_pos()))
|
" nella cassa delle donazioni da " .. core.pos_to_string(player:get_pos()))
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
@ -15,7 +15,7 @@ Queste proprietà sono fisse, uguali per tutte le istanze, tuttavia è possibile
|
|||||||
|
|
||||||
Il concetto di nodo è stato introdotto nello scorso capitolo, ma non è mai stata data una definizione completa.
|
Il concetto di nodo è stato introdotto nello scorso capitolo, ma non è mai stata data una definizione completa.
|
||||||
Il mondo di Minetest è una griglia 3D: un nodo è un punto di quella griglia ed è composto da un tipo (`name`) e due parametri (`param1` e `param2`).
|
Il mondo di Minetest è una griglia 3D: un nodo è un punto di quella griglia ed è composto da un tipo (`name`) e due parametri (`param1` e `param2`).
|
||||||
Non farti inoltre ingannare dalla funzione `minetest.register_node`, in quanto è un po' fuorviante: essa non registra infatti un nuovo nodo (c'è solo una definizione di nodo), bensì un nuovo *tipo* di nodo.
|
Non farti inoltre ingannare dalla funzione `core.register_node`, in quanto è un po' fuorviante: essa non registra infatti un nuovo nodo (c'è solo una definizione di nodo), bensì un nuovo *tipo* di nodo.
|
||||||
|
|
||||||
I parametri sono infine usati per controllare come un nodo viene renderizzato individualmente: `param1` immagazzina le proprietà di luce, mentre il ruolo di `param2` dipende dalla proprietà `paramtype2`, la quale è situata nella definizione dei singoli tipi.
|
I parametri sono infine usati per controllare come un nodo viene renderizzato individualmente: `param1` immagazzina le proprietà di luce, mentre il ruolo di `param2` dipende dalla proprietà `paramtype2`, la quale è situata nella definizione dei singoli tipi.
|
||||||
|
|
||||||
@ -51,13 +51,13 @@ Ciò è buono per quei nodi con facce in parte trasparenti come le foglie.
|
|||||||
Puoi inoltre usare il drawtype `allfaces_optional` per permettere agli utenti di fare opt-out dal rendering più pesante, facendo comportare il nodo come se fosse di tipo normale.
|
Puoi inoltre usare il drawtype `allfaces_optional` per permettere agli utenti di fare opt-out dal rendering più pesante, facendo comportare il nodo come se fosse di tipo normale.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("miamod:diamante", {
|
core.register_node("miamod:diamante", {
|
||||||
description = "Diamante alieno",
|
description = "Diamante alieno",
|
||||||
tiles = {"miamod_diamante.png"},
|
tiles = {"miamod_diamante.png"},
|
||||||
groups = {cracky = 3},
|
groups = {cracky = 3},
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("default:foglie", {
|
core.register_node("default:foglie", {
|
||||||
description = "Foglie",
|
description = "Foglie",
|
||||||
drawtype = "allfaces_optional",
|
drawtype = "allfaces_optional",
|
||||||
tiles = {"default_foglie.png"}
|
tiles = {"default_foglie.png"}
|
||||||
@ -79,7 +79,7 @@ Questo è utile in quanto i nodi vitrei tendono a essere trasparenti, perciò pe
|
|||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("default:obsidian_glass", {
|
core.register_node("default:obsidian_glass", {
|
||||||
description = "Vetro d'ossidiana",
|
description = "Vetro d'ossidiana",
|
||||||
drawtype = "glasslike",
|
drawtype = "glasslike",
|
||||||
tiles = {"default_obsidian_glass.png"},
|
tiles = {"default_obsidian_glass.png"},
|
||||||
@ -103,11 +103,11 @@ Questa opzione crea un solo bordo lungo tutto l'insieme di nodi, al posto di cre
|
|||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("default:glass", {
|
core.register_node("default:glass", {
|
||||||
description = "Vetro",
|
description = "Vetro",
|
||||||
drawtype = "glasslike_framed",
|
drawtype = "glasslike_framed",
|
||||||
tiles = {"default_glass.png", "default_glass_detail.png"},
|
tiles = {"default_glass.png", "default_glass_detail.png"},
|
||||||
inventory_image = minetest.inventorycube("default_glass.png"),
|
inventory_image = core.inventorycube("default_glass.png"),
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
sunlight_propagates = true, -- Sunlight can shine through block
|
sunlight_propagates = true, -- Sunlight can shine through block
|
||||||
groups = {cracky = 3, oddly_breakable_by_hand = 3},
|
groups = {cracky = 3, oddly_breakable_by_hand = 3},
|
||||||
@ -122,7 +122,7 @@ Puoi inoltre usare il *drawtype* `glasslike_framed_optional` per permettere un o
|
|||||||
I nodi d'aria (*airlike*) non sono renderizzati e perciò non hanno texture.
|
I nodi d'aria (*airlike*) non sono renderizzati e perciò non hanno texture.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("miaaria:aria", {
|
core.register_node("miaaria:aria", {
|
||||||
description = "Mia Aria",
|
description = "Mia Aria",
|
||||||
drawtype = "airlike",
|
drawtype = "airlike",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
@ -172,11 +172,11 @@ Ogni tipo di liquido richiede due definizioni di nodi: una per la sorgente e l'a
|
|||||||
```lua
|
```lua
|
||||||
-- Alcune proprietà sono state rimosse perché non
|
-- Alcune proprietà sono state rimosse perché non
|
||||||
-- rilevanti per questo capitolo
|
-- rilevanti per questo capitolo
|
||||||
minetest.register_node("default:water_source", {
|
core.register_node("default:water_source", {
|
||||||
drawtype = "liquid",
|
drawtype = "liquid",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
|
|
||||||
inventory_image = minetest.inventorycube("default_water.png"),
|
inventory_image = core.inventorycube("default_water.png"),
|
||||||
-- ^ questo è necessario per impedire che l'immagine nell'inventario sia animata
|
-- ^ questo è necessario per impedire che l'immagine nell'inventario sia animata
|
||||||
|
|
||||||
tiles = {
|
tiles = {
|
||||||
@ -250,7 +250,7 @@ Guarda default:water_flowing nella mod default di minetest_game per un esempio c
|
|||||||
I nodi complessi (*nodebox*) ti permettono di creare un nodo che non è cubico, bensì un insieme di più cuboidi.
|
I nodi complessi (*nodebox*) ti permettono di creare un nodo che non è cubico, bensì un insieme di più cuboidi.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("stairs:stair_stone", {
|
core.register_node("stairs:stair_stone", {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
node_box = {
|
node_box = {
|
||||||
@ -281,7 +281,7 @@ Puoi usare [NodeBoxEditor](https://forum.minetest.net/viewtopic.php?f=14&t=2840)
|
|||||||
Certe volte si vogliono avere nodi complessi che cambiano a seconda della loro posizione sul pavimento, sul muro e sul soffitto, come le torce.
|
Certe volte si vogliono avere nodi complessi che cambiano a seconda della loro posizione sul pavimento, sul muro e sul soffitto, come le torce.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("default:sign_wall", {
|
core.register_node("default:sign_wall", {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
node_box = {
|
node_box = {
|
||||||
type = "wallmounted",
|
type = "wallmounted",
|
||||||
@ -315,7 +315,7 @@ Una faccia interna appare quando le facce di due nodi complessi si sovrappongono
|
|||||||
Puoi registrare un nodo mesh come segue:
|
Puoi registrare un nodo mesh come segue:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("miamod:meshy", {
|
core.register_node("miamod:meshy", {
|
||||||
drawtype = "mesh",
|
drawtype = "mesh",
|
||||||
|
|
||||||
-- Contiene le texture di ogni materiale
|
-- Contiene le texture di ogni materiale
|
||||||
@ -340,7 +340,7 @@ Al contrario del loro nome, i cartelli non rientrano nei nodi insegna bensì in
|
|||||||
I tipi insegna tuttavia, sono comunemente usati dalle scale a pioli.
|
I tipi insegna tuttavia, sono comunemente usati dalle scale a pioli.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("default:ladder_wood", {
|
core.register_node("default:ladder_wood", {
|
||||||
drawtype = "signlike",
|
drawtype = "signlike",
|
||||||
|
|
||||||
tiles = {"default_ladder_wood.png"},
|
tiles = {"default_ladder_wood.png"},
|
||||||
@ -366,7 +366,7 @@ minetest.register_node("default:ladder_wood", {
|
|||||||
I nodi pianta (*plantlike*) raffigurano la loro texture in un pattern a forma di X.
|
I nodi pianta (*plantlike*) raffigurano la loro texture in un pattern a forma di X.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("default:papyrus", {
|
core.register_node("default:papyrus", {
|
||||||
drawtype = "plantlike",
|
drawtype = "plantlike",
|
||||||
|
|
||||||
-- Viene usata solo una texture
|
-- Viene usata solo una texture
|
||||||
@ -391,7 +391,7 @@ I nodi fiamma (*firelike*) sono simili ai pianta, ad eccezione del fatto che son
|
|||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("miamod:avvinghiatutto", {
|
core.register_node("miamod:avvinghiatutto", {
|
||||||
drawtype = "firelike",
|
drawtype = "firelike",
|
||||||
|
|
||||||
-- Viene usata solo una texture
|
-- Viene usata solo una texture
|
||||||
|
@ -43,7 +43,7 @@ Le definizioni degli oggetti consistono in un *nome oggetto* e una *tabella di d
|
|||||||
La tabella di definizioni contiene attributi che influenzano il comportamento dell'oggetto.
|
La tabella di definizioni contiene attributi che influenzano il comportamento dell'oggetto.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craftitem("nomemod:nomeoggetto", {
|
core.register_craftitem("nomemod:nomeoggetto", {
|
||||||
description = "Il Mio Super Oggetto",
|
description = "Il Mio Super Oggetto",
|
||||||
inventory_image = "nomemod_nomeoggetto.png"
|
inventory_image = "nomemod_nomeoggetto.png"
|
||||||
})
|
})
|
||||||
@ -72,7 +72,7 @@ Ciò è comunemente usato in due casi:
|
|||||||
Registrare un alias è alquanto semplice.
|
Registrare un alias è alquanto semplice.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_alias("dirt", "default:dirt")
|
core.register_alias("dirt", "default:dirt")
|
||||||
```
|
```
|
||||||
|
|
||||||
Un buon modo per ricordarne il funzionamento è `da → a`, dove *da*
|
Un buon modo per ricordarne il funzionamento è `da → a`, dove *da*
|
||||||
@ -82,7 +82,7 @@ Le mod devono inoltre assicurarsi di elaborare gli alias prima di occuparsi dire
|
|||||||
Anche in questo caso non è difficile:
|
Anche in questo caso non è difficile:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
itemname = minetest.registered_aliases[itemname] or itemname
|
itemname = core.registered_aliases[itemname] or itemname
|
||||||
```
|
```
|
||||||
|
|
||||||
### Texture
|
### Texture
|
||||||
@ -98,7 +98,7 @@ Questo perché dimensioni differenti potrebbero non essere supportate dai vecchi
|
|||||||
## Registrare un nodo base
|
## Registrare un nodo base
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("miamod:diamante", {
|
core.register_node("miamod:diamante", {
|
||||||
description = "Diamante alieno",
|
description = "Diamante alieno",
|
||||||
tiles = {"miamod_diamante.png"},
|
tiles = {"miamod_diamante.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
@ -116,7 +116,7 @@ Per assegnarne invece di diverse, bisogna fornire il nome di 6 texture in quest'
|
|||||||
Ricorda che su Minetest, come nella convenzione della computer grafica 3D, +Y punta verso l'alto.
|
Ricorda che su Minetest, come nella convenzione della computer grafica 3D, +Y punta verso l'alto.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("miamod:diamante", {
|
core.register_node("miamod:diamante", {
|
||||||
description = "Diamante alieno",
|
description = "Diamante alieno",
|
||||||
tiles = {
|
tiles = {
|
||||||
"miamod_diamante_up.png", -- y+
|
"miamod_diamante_up.png", -- y+
|
||||||
@ -154,7 +154,7 @@ Le ricette fisse avvengono quando gli ingredienti devono essere nella forma o se
|
|||||||
Nell'esempio sotto, i frammenti necessitano di essere in una figura a forma di sedia per poter fabbricare appunto 99 sedie.
|
Nell'esempio sotto, i frammenti necessitano di essere in una figura a forma di sedia per poter fabbricare appunto 99 sedie.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
type = "shaped",
|
type = "shaped",
|
||||||
output = "miamod:diamante_sedia 99",
|
output = "miamod:diamante_sedia 99",
|
||||||
recipe = {
|
recipe = {
|
||||||
@ -170,7 +170,7 @@ Questo significa che ci *deve* essere una colonna vuota a destra della forma, al
|
|||||||
Se invece la colonna non dovesse servire, basta ometterla in questo modo:
|
Se invece la colonna non dovesse servire, basta ometterla in questo modo:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
output = "miamod:diamante_sedia 99",
|
output = "miamod:diamante_sedia 99",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"miamod:diamante_frammenti", "" },
|
{"miamod:diamante_frammenti", "" },
|
||||||
@ -187,7 +187,7 @@ Il campo type non è davvero necessario per le ricette fisse, in quanto sono il
|
|||||||
Le ricette informi sono ricette che vengono usate quando non importa dove sono posizionati gli ingredienti, ma solo che ci siano.
|
Le ricette informi sono ricette che vengono usate quando non importa dove sono posizionati gli ingredienti, ma solo che ci siano.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
type = "shapeless",
|
type = "shapeless",
|
||||||
output = "miamod:diamante 3",
|
output = "miamod:diamante 3",
|
||||||
recipe = {
|
recipe = {
|
||||||
@ -203,7 +203,7 @@ minetest.register_craft({
|
|||||||
Le ricette di tipo "cottura" non vengono elaborate nella griglia di fabbricazione, bensì nelle fornaci o in qualsivoglia altro strumento di cottura che può essere trovato nelle mod.
|
Le ricette di tipo "cottura" non vengono elaborate nella griglia di fabbricazione, bensì nelle fornaci o in qualsivoglia altro strumento di cottura che può essere trovato nelle mod.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
type = "cooking",
|
type = "cooking",
|
||||||
output = "miamod_diamante_frammenti",
|
output = "miamod_diamante_frammenti",
|
||||||
recipe = "default:coalblock",
|
recipe = "default:coalblock",
|
||||||
@ -220,7 +220,7 @@ La ricetta qui sopra genera un'unità di frammenti di diamante dopo 10 secondi q
|
|||||||
Il tipo "carburante" invece funge da accompagnamento alle ricette di cottura, in quanto definisce cosa può alimentare il fuoco.
|
Il tipo "carburante" invece funge da accompagnamento alle ricette di cottura, in quanto definisce cosa può alimentare il fuoco.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
type = "fuel",
|
type = "fuel",
|
||||||
recipe = "miamod:diamante",
|
recipe = "miamod:diamante",
|
||||||
burntime = 300,
|
burntime = 300,
|
||||||
@ -244,7 +244,7 @@ In primis, vengono utilizzati per descrivere proprietà come friabilità e infia
|
|||||||
In secundis, possono essere usati in una ricetta al posto di un nome oggetto per permettere a qualsiasi oggetto nel gruppo di essere utilizzato.
|
In secundis, possono essere usati in una ricetta al posto di un nome oggetto per permettere a qualsiasi oggetto nel gruppo di essere utilizzato.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_craft({
|
core.register_craft({
|
||||||
type = "shapeless",
|
type = "shapeless",
|
||||||
output = "miamod:diamante_qualcosa 3",
|
output = "miamod:diamante_qualcosa 3",
|
||||||
recipe = {"group:wood", "miamod:diamante"}
|
recipe = {"group:wood", "miamod:diamante"}
|
||||||
@ -275,7 +275,7 @@ Gli strumenti possono anche avere una durezza massima supportata per ogni tipo;
|
|||||||
Se l'oggetto impugnato dal giocatore non ha una capacità esplicitata, verrà allora usata quella della mano.
|
Se l'oggetto impugnato dal giocatore non ha una capacità esplicitata, verrà allora usata quella della mano.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_tool("miamod:strumento", {
|
core.register_tool("miamod:strumento", {
|
||||||
description = "Il mio strumento",
|
description = "Il mio strumento",
|
||||||
inventory_image = "miamod_strumento.png",
|
inventory_image = "miamod_strumento.png",
|
||||||
tool_capabilities = {
|
tool_capabilities = {
|
||||||
|
@ -44,7 +44,7 @@ I Blocchi Mappa esistenti, tuttavia, ignorano questo limite quando caricati dal
|
|||||||
Un nodo può essere letto da un mondo fornendone la posizione:
|
Un nodo può essere letto da un mondo fornendone la posizione:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local nodo = minetest.get_node({ x = 1, y = 3, z = 4 })
|
local nodo = core.get_node({ x = 1, y = 3, z = 4 })
|
||||||
print(dump(nodo)) --> { name=.., param1=.., param2=.. }
|
print(dump(nodo)) --> { name=.., param1=.., param2=.. }
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ Se la posizione è un decimale, verrà arrotondata alle coordinate del nodo.
|
|||||||
* `param1` - Guarda la definizione dei nodi. È solitamente associato alla luce.
|
* `param1` - Guarda la definizione dei nodi. È solitamente associato alla luce.
|
||||||
* `param2` - Guarda la definizione dei nodi.
|
* `param2` - Guarda la definizione dei nodi.
|
||||||
|
|
||||||
Per vedere se un nodo è caricato si può utilizzare `minetest.get_node_or_nil`, che ritornerà `nil` se il nome del nodo risulta `ignore`
|
Per vedere se un nodo è caricato si può utilizzare `core.get_node_or_nil`, che ritornerà `nil` se il nome del nodo risulta `ignore`
|
||||||
(la funzione non caricherà comunque il nodo).
|
(la funzione non caricherà comunque il nodo).
|
||||||
Potrebbe comunque ritornare `ignore` se un blocco contiene effettivamente `ignore`: questo succede ai limiti della mappa.
|
Potrebbe comunque ritornare `ignore` se un blocco contiene effettivamente `ignore`: questo succede ai limiti della mappa.
|
||||||
|
|
||||||
@ -67,14 +67,14 @@ Le più frequenti sono quelle per trovare i nodi.
|
|||||||
Per esempio, mettiamo che si voglia creare un certo tipo di pianta che cresce più velocemente vicino alla pietra;
|
Per esempio, mettiamo che si voglia creare un certo tipo di pianta che cresce più velocemente vicino alla pietra;
|
||||||
si dovrebbe controllare che ogni nodo nei pressi della pianta sia pietra, e modificarne il suo indice di crescita di conseguenza.
|
si dovrebbe controllare che ogni nodo nei pressi della pianta sia pietra, e modificarne il suo indice di crescita di conseguenza.
|
||||||
|
|
||||||
`minetest.find_node_near` ritornerà il primo nodo trovato in un dato raggio, combaciante con le informazioni passategli (nomi di nodi o gruppi).
|
`core.find_node_near` ritornerà il primo nodo trovato in un dato raggio, combaciante con le informazioni passategli (nomi di nodi o gruppi).
|
||||||
Nell'esempio che segue, andiamo alla ricerca di un nodo di mese nel raggio di 5 nodi:
|
Nell'esempio che segue, andiamo alla ricerca di un nodo di mese nel raggio di 5 nodi:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local vel_crescita = 1
|
local vel_crescita = 1
|
||||||
local pos_nodo = minetest.find_node_near(pos, 5, { "default:stone" })
|
local pos_nodo = core.find_node_near(pos, 5, { "default:stone" })
|
||||||
if pos_nodo then
|
if pos_nodo then
|
||||||
minetest.chat_send_all("Nodo trovato a: " .. dump(pos_nodo))
|
core.chat_send_all("Nodo trovato a: " .. dump(pos_nodo))
|
||||||
vel_crescita = 2
|
vel_crescita = 2
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
@ -86,7 +86,7 @@ Si dovrebbe quindi usare una funzione in grado di trovare più nodi in un'area:
|
|||||||
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
||||||
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
||||||
local lista_pos =
|
local lista_pos =
|
||||||
minetest.find_nodes_in_area(pos1, pos2, { "default:stone" })
|
core.find_nodes_in_area(pos1, pos2, { "default:stone" })
|
||||||
local vel_crescita = 1 + #lista_pos
|
local vel_crescita = 1 + #lista_pos
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ Per ovviare a ciò, bisogna controllare l'intervallo manualmente.
|
|||||||
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
||||||
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
||||||
local lista_pos =
|
local lista_pos =
|
||||||
minetest.find_nodes_in_area(pos1, pos2, { "default:stone" })
|
core.find_nodes_in_area(pos1, pos2, { "default:stone" })
|
||||||
local vel_crescita = 1
|
local vel_crescita = 1
|
||||||
for i=1, #lista_pos do
|
for i=1, #lista_pos do
|
||||||
local delta = vector.subtract(lista_pos[i], pos)
|
local delta = vector.subtract(lista_pos[i], pos)
|
||||||
@ -123,9 +123,9 @@ Puoi usare `set_node` per sovrascrivere nodi nella mappa.
|
|||||||
Ogni chiamata a `set_node` ricalcolerà la luce e richiamerà i suoi callback, il che significa che `set_node` è alquanto lento quando usato su un elevato numero di nodi.
|
Ogni chiamata a `set_node` ricalcolerà la luce e richiamerà i suoi callback, il che significa che `set_node` è alquanto lento quando usato su un elevato numero di nodi.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.set_node({ x = 1, y = 3, z = 4 }, { name = "default:stone" })
|
core.set_node({ x = 1, y = 3, z = 4 }, { name = "default:stone" })
|
||||||
|
|
||||||
local nodo = minetest.get_node({ x = 1, y = 3, z = 4 })
|
local nodo = core.get_node({ x = 1, y = 3, z = 4 })
|
||||||
print(nodo.name) --> default:stone
|
print(nodo.name) --> default:stone
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ sono in verità due.
|
|||||||
Si può impostare un nuovo nodo senza rimuoverne metadati e inventario con `swap_node`:
|
Si può impostare un nuovo nodo senza rimuoverne metadati e inventario con `swap_node`:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.swap_node({ x = 1, y = 3, z = 4 }, { name = "default:stone" })
|
core.swap_node({ x = 1, y = 3, z = 4 }, { name = "default:stone" })
|
||||||
```
|
```
|
||||||
|
|
||||||
### Rimozione dei nodi
|
### Rimozione dei nodi
|
||||||
@ -146,15 +146,15 @@ Un nodo deve sempre essere presente. Per rimuoverlo, basta impostarlo uguale a `
|
|||||||
Le seguenti due linee di codice sono equivalenti, rimuovendo in entrambi i casi il nodo:
|
Le seguenti due linee di codice sono equivalenti, rimuovendo in entrambi i casi il nodo:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.remove_node(pos)
|
core.remove_node(pos)
|
||||||
minetest.set_node(pos, { name = "air" })
|
core.set_node(pos, { name = "air" })
|
||||||
```
|
```
|
||||||
|
|
||||||
Infatti, `remove_node` non fa altro che richiamare `set_node` con nome `air`.
|
Infatti, `remove_node` non fa altro che richiamare `set_node` con nome `air`.
|
||||||
|
|
||||||
## Caricamento blocchi
|
## Caricamento blocchi
|
||||||
|
|
||||||
Puoi usare `minetest.emerge_area` per caricare i blocchi mappa.
|
Puoi usare `core.emerge_area` per caricare i blocchi mappa.
|
||||||
Questo comando è asincrono, ovvero i blocchi non saranno caricati istantaneamente; al contrario, verranno caricati man mano e il callback associato sarà richiamato a ogni passaggio.
|
Questo comando è asincrono, ovvero i blocchi non saranno caricati istantaneamente; al contrario, verranno caricati man mano e il callback associato sarà richiamato a ogni passaggio.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
@ -164,7 +164,7 @@ local pos1 = vector.subtract(pos, mezza_dimensione)
|
|||||||
local pos2 = vector.add (pos, mezza_dimensione)
|
local pos2 = vector.add (pos, mezza_dimensione)
|
||||||
|
|
||||||
local param = {} -- dati persistenti tra un callback e l'altro
|
local param = {} -- dati persistenti tra un callback e l'altro
|
||||||
minetest.emerge_area(pos1, pos2, mio_callback, param)
|
core.emerge_area(pos1, pos2, mio_callback, param)
|
||||||
```
|
```
|
||||||
|
|
||||||
Minetest chiamerà la funzione locale definita qua sotto `mio_callback` ogni volta che carica un blocco, con delle informazioni sul progresso.
|
Minetest chiamerà la funzione locale definita qua sotto `mio_callback` ogni volta che carica un blocco, con delle informazioni sul progresso.
|
||||||
@ -183,12 +183,12 @@ local function mio_callback(pos, action,
|
|||||||
|
|
||||||
-- Invia messaggio indicante il progresso
|
-- Invia messaggio indicante il progresso
|
||||||
if param.blocchi_totali == param.blocchi_caricati then
|
if param.blocchi_totali == param.blocchi_caricati then
|
||||||
minetest.chat_send_all("Ho finito di caricare blocchi!")
|
core.chat_send_all("Ho finito di caricare blocchi!")
|
||||||
else
|
else
|
||||||
local percentuale = 100 * param.blocchi_caricati / param.blocchi_totali
|
local percentuale = 100 * param.blocchi_caricati / param.blocchi_totali
|
||||||
local msg = string.format("Caricamento blocchi %d/%d (%.2f%%)",
|
local msg = string.format("Caricamento blocchi %d/%d (%.2f%%)",
|
||||||
param.blocchi_caricati, param.blocchi_totali, percentuale)
|
param.blocchi_caricati, param.blocchi_totali, percentuale)
|
||||||
minetest.chat_send_all(msg)
|
core.chat_send_all(msg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
@ -205,7 +205,7 @@ local mezza_dimensione = { x = 10, y = 10, z = 10 }
|
|||||||
local pos1 = vector.subtract(pos, mezza_dimensione)
|
local pos1 = vector.subtract(pos, mezza_dimensione)
|
||||||
local pos2 = vector.add (pos, mezza_dimensione)
|
local pos2 = vector.add (pos, mezza_dimensione)
|
||||||
|
|
||||||
minetest.delete_area(pos1, pos2)
|
core.delete_area(pos1, pos2)
|
||||||
```
|
```
|
||||||
|
|
||||||
Questo cancellerà tutti i blocchi mappa in quell'area, anche quelli solo parzialmente selezionati.
|
Questo cancellerà tutti i blocchi mappa in quell'area, anche quelli solo parzialmente selezionati.
|
||||||
|
@ -43,7 +43,7 @@ Questa distinzione è resa meno chiara dal fatto che le entità sono controllate
|
|||||||
`get_pos` e `set_pos` permettono di ottenere e impostare la posizione di un oggetto.
|
`get_pos` e `set_pos` permettono di ottenere e impostare la posizione di un oggetto.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local giocatore = minetest.get_player_by_name("bob")
|
local giocatore = core.get_player_by_name("bob")
|
||||||
local pos = giocatore:get_pos()
|
local pos = giocatore:get_pos()
|
||||||
giocatore:set_pos({ x = pos.x, y = pos.y + 1, z = pos.z })
|
giocatore:set_pos({ x = pos.x, y = pos.y + 1, z = pos.z })
|
||||||
```
|
```
|
||||||
@ -130,7 +130,7 @@ Sia la tabella di un ObjectRef che quella di un'entità forniscono modi per otte
|
|||||||
```lua
|
```lua
|
||||||
local entita = oggetto:get_luaentity()
|
local entita = oggetto:get_luaentity()
|
||||||
local oggetto = entita.object
|
local oggetto = entita.object
|
||||||
print("L'entità si trova a " .. minetest.pos_to_string(oggetto:get_pos()))
|
print("L'entità si trova a " .. core.pos_to_string(oggetto:get_pos()))
|
||||||
```
|
```
|
||||||
|
|
||||||
Ci sono diversi callback disponibili da usare per le entità.
|
Ci sono diversi callback disponibili da usare per le entità.
|
||||||
@ -142,9 +142,9 @@ function MiaEntita:on_step(dtime)
|
|||||||
local pos_giu = vector.subtract(pos, vector.new(0, 1, 0))
|
local pos_giu = vector.subtract(pos, vector.new(0, 1, 0))
|
||||||
|
|
||||||
local delta
|
local delta
|
||||||
if minetest.get_node(pos_giu).name == "air" then
|
if core.get_node(pos_giu).name == "air" then
|
||||||
delta = vector.new(0, -1, 0)
|
delta = vector.new(0, -1, 0)
|
||||||
elseif minetest.get_node(pos).name == "air" then
|
elseif core.get_node(pos).name == "air" then
|
||||||
delta = vector.new(0, 0, 1)
|
delta = vector.new(0, 0, 1)
|
||||||
else
|
else
|
||||||
delta = vector.new(0, 1, 0)
|
delta = vector.new(0, 1, 0)
|
||||||
@ -156,7 +156,7 @@ function MiaEntita:on_step(dtime)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MiaEntita:on_punch(hitter)
|
function MiaEntita:on_punch(hitter)
|
||||||
minetest.chat_send_player(hitter:get_player_name(), self.message)
|
core.chat_send_player(hitter:get_player_name(), self.message)
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -167,14 +167,14 @@ Questo succede nella *Staticdata*, una stringa che contiene tutte le informazion
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
function MiaEntita:get_staticdata()
|
function MiaEntita:get_staticdata()
|
||||||
return minetest.write_json({
|
return core.write_json({
|
||||||
messaggio = self.messaggio,
|
messaggio = self.messaggio,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function MiaEntita:on_activate(staticdata, dtime_s)
|
function MiaEntita:on_activate(staticdata, dtime_s)
|
||||||
if staticdata ~= "" and staticdata ~= nil then
|
if staticdata ~= "" and staticdata ~= nil then
|
||||||
local data = minetest.parse_json(staticdata) or {}
|
local data = core.parse_json(staticdata) or {}
|
||||||
self:imposta_messaggio(data.messaggio)
|
self:imposta_messaggio(data.messaggio)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -190,14 +190,14 @@ Questo significa che il suo staticdata inizialmente potrebbe essere vuoto (dato
|
|||||||
Infine, c'è bisogno di registrare la tabella usando `register_entity`.
|
Infine, c'è bisogno di registrare la tabella usando `register_entity`.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_entity("miamod:entita", MiaEntita)
|
core.register_entity("miamod:entita", MiaEntita)
|
||||||
```
|
```
|
||||||
|
|
||||||
L'entità può essere spawnata da una mod nel seguente modo:
|
L'entità può essere spawnata da una mod nel seguente modo:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local pos = { x = 1, y = 2, z = 3 }
|
local pos = { x = 1, y = 2, z = 3 }
|
||||||
local oggetto = minetest.add_entity(pos, "miamod:entita", nil)
|
local oggetto = core.add_entity(pos, "miamod:entita", nil)
|
||||||
```
|
```
|
||||||
|
|
||||||
Il terzo parametro è lo staticdata inziale.
|
Il terzo parametro è lo staticdata inziale.
|
||||||
|
@ -14,14 +14,14 @@ redirect_from:
|
|||||||
In questo capitolo imparerai i vari modi per immagazzinare dati.
|
In questo capitolo imparerai i vari modi per immagazzinare dati.
|
||||||
|
|
||||||
- [Metadati](#metadati)
|
- [Metadati](#metadati)
|
||||||
- [Cos'è un metadato?](#cos-e-un-metadato)
|
- [Cos'è un metadato?](#cosè-un-metadato)
|
||||||
- [Ottenere i metadati di un oggetto](#ottenere-i-metadati-di-un-oggetto)
|
- [Ottenere i metadati di un oggetto](#ottenere-i-metadati-di-un-oggetto)
|
||||||
- [Lettura e scrittura](#lettura-e-scrittura)
|
- [Lettura e scrittura](#lettura-e-scrittura)
|
||||||
- [Chiavi speciali](#chiavi-speciali)
|
- [Chiavi speciali](#chiavi-speciali)
|
||||||
- [Immagazzinare tabelle](#immagazzinare-tabelle)
|
- [Immagazzinare tabelle](#immagazzinare-tabelle)
|
||||||
- [Metadati privati](#metadati-privati)
|
- [Metadati privati](#metadati-privati)
|
||||||
- [Tabelle Lua](#tabelle-lua)
|
- [Tabelle Lua](#tabelle-lua)
|
||||||
- [Storaggio mod](#storaggio-mod)
|
- [Storaggio Mod](#storaggio-mod)
|
||||||
- [Database](#database)
|
- [Database](#database)
|
||||||
- [Decidere quale usare](#decidere-quale-usare)
|
- [Decidere quale usare](#decidere-quale-usare)
|
||||||
- [Il tuo turno](#il-tuo-turno)
|
- [Il tuo turno](#il-tuo-turno)
|
||||||
@ -47,7 +47,7 @@ Il dato in sé, come il tipo di un nodo o la quantità di un ItemStack, non rien
|
|||||||
Se si conosce la posizione di un nodo, si possono ottenere i suoi metadati:
|
Se si conosce la posizione di un nodo, si possono ottenere i suoi metadati:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local meta = minetest.get_meta({ x = 1, y = 2, z = 3 })
|
local meta = core.get_meta({ x = 1, y = 2, z = 3 })
|
||||||
```
|
```
|
||||||
|
|
||||||
Quelli dei giocatori e degli ItemStack invece sono ottenuti tramite `get_meta()`:
|
Quelli dei giocatori e degli ItemStack invece sono ottenuti tramite `get_meta()`:
|
||||||
@ -87,7 +87,7 @@ print(meta:get_string("count")) --> "3"
|
|||||||
Questo è utile, per esempio, per mostrare lo stato o il proprietario di un nodo.
|
Questo è utile, per esempio, per mostrare lo stato o il proprietario di un nodo.
|
||||||
|
|
||||||
`description` è usato negli ItemStack per sovrascrivere la descrizione al passare il mouse sopra l'oggetto in un formspec (come l'inventario, li vedremo più avanti).
|
`description` è usato negli ItemStack per sovrascrivere la descrizione al passare il mouse sopra l'oggetto in un formspec (come l'inventario, li vedremo più avanti).
|
||||||
È possibile utilizzare `minetest.colorize()` per cambiarne il colore.
|
È possibile utilizzare `core.colorize()` per cambiarne il colore.
|
||||||
|
|
||||||
`owner` è una chiave comune, usata per immagazzinare il nome del giocatore a cui appartiene l'oggetto o il nodo.
|
`owner` è una chiave comune, usata per immagazzinare il nome del giocatore a cui appartiene l'oggetto o il nodo.
|
||||||
|
|
||||||
@ -100,9 +100,9 @@ Quello in Lua tende a essere molto più veloce e corrisponde al formato usato da
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
local data = { username = "utente1", score = 1234 }
|
local data = { username = "utente1", score = 1234 }
|
||||||
meta:set_string("foo", minetest.serialize(data))
|
meta:set_string("foo", core.serialize(data))
|
||||||
|
|
||||||
data = minetest.deserialize(minetest:get_string("foo"))
|
data = core.deserialize(meta:get_string("foo"))
|
||||||
```
|
```
|
||||||
|
|
||||||
### Metadati privati
|
### Metadati privati
|
||||||
@ -130,7 +130,7 @@ Lo spazio d'archiviazione della mod (*storage*) usa la stessa identica API dei m
|
|||||||
Il primo infatti è per mod, e può essere ottenuto solo durante l'inizializzazione - appunto - della mod.
|
Il primo infatti è per mod, e può essere ottenuto solo durante l'inizializzazione - appunto - della mod.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local memoria = minetest.get_mod_storage()
|
local memoria = core.get_mod_storage()
|
||||||
```
|
```
|
||||||
|
|
||||||
Nell'esempio è ora possibile manipolare lo spazio d'archiviazione come se fosse un metadato:
|
Nell'esempio è ora possibile manipolare lo spazio d'archiviazione come se fosse un metadato:
|
||||||
@ -148,10 +148,10 @@ Dovresti rendere ciò opzionale, separando il come i dati vengono salvati e il d
|
|||||||
local backend
|
local backend
|
||||||
if use_database then
|
if use_database then
|
||||||
backend =
|
backend =
|
||||||
dofile(minetest.get_modpath("miamod") .. "/backend_sqlite.lua")
|
dofile(core.get_modpath("miamod") .. "/backend_sqlite.lua")
|
||||||
else
|
else
|
||||||
backend =
|
backend =
|
||||||
dofile(minetest.get_modpath("miamod") .. "/backend_storage.lua")
|
dofile(core.get_modpath("miamod") .. "/backend_storage.lua")
|
||||||
end
|
end
|
||||||
|
|
||||||
backend.get_foo("a")
|
backend.get_foo("a")
|
||||||
@ -161,15 +161,15 @@ backend.set_foo("a", { score = 3 })
|
|||||||
Il file `backend_storage.lua` dell'esempio (puoi nominarlo come vuoi) dovrebbe includere l'implementazione del metodo di storaggio:
|
Il file `backend_storage.lua` dell'esempio (puoi nominarlo come vuoi) dovrebbe includere l'implementazione del metodo di storaggio:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local memoria = minetest.get_mod_storage()
|
local memoria = core.get_mod_storage()
|
||||||
local backend = {}
|
local backend = {}
|
||||||
|
|
||||||
function backend.set_foo(key, value)
|
function backend.set_foo(key, value)
|
||||||
memoria:set_string(key, minetest.serialize(value))
|
memoria:set_string(key, core.serialize(value))
|
||||||
end
|
end
|
||||||
|
|
||||||
function backend.get_foo(key)
|
function backend.get_foo(key)
|
||||||
return minetest.deserialize(memoria:get_string(key))
|
return core.deserialize(memoria:get_string(key))
|
||||||
end
|
end
|
||||||
|
|
||||||
return backend
|
return backend
|
||||||
@ -182,7 +182,7 @@ Un ambiente non sicuro è una tabella disponibile solamente alle mod con accesso
|
|||||||
Gli ambienti non sicuri saranno trattati più nel dettaglio nel capitolo sulla [Sicurezza](../quality/security.html).
|
Gli ambienti non sicuri saranno trattati più nel dettaglio nel capitolo sulla [Sicurezza](../quality/security.html).
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local amb_nonsicuro = minetest.request_insecure_environment()
|
local amb_nonsicuro = core.request_insecure_environment()
|
||||||
assert(amb_nonsicuro, "Per favore aggiungi miamod a secure.trusted_mods nelle impostazioni")
|
assert(amb_nonsicuro, "Per favore aggiungi miamod a secure.trusted_mods nelle impostazioni")
|
||||||
|
|
||||||
local _sql = amb_nonsicuro.require("lsqlite3")
|
local _sql = amb_nonsicuro.require("lsqlite3")
|
||||||
@ -214,4 +214,4 @@ Si prestano bene per i grandi ammontare di dati.
|
|||||||
## Il tuo turno
|
## Il tuo turno
|
||||||
|
|
||||||
* Crea un nodo che sparisce dopo essere stato colpito cinque volte.
|
* Crea un nodo che sparisce dopo essere stato colpito cinque volte.
|
||||||
(Usa `on_punch` nella definizione del nodo e `minetest.set_node`)
|
(Usa `on_punch` nella definizione del nodo e `core.set_node`)
|
||||||
|
@ -32,7 +32,7 @@ A ogni nodo è associato un timer.
|
|||||||
Questi timer possono essere gestiti ottenendo un oggetto NodeTimerRef (quindi un riferimento, come già visto per gli inventari).
|
Questi timer possono essere gestiti ottenendo un oggetto NodeTimerRef (quindi un riferimento, come già visto per gli inventari).
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local timer = minetest.get_node_timer(pos)
|
local timer = core.get_node_timer(pos)
|
||||||
timer:start(10.5) -- in secondi
|
timer:start(10.5) -- in secondi
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -40,9 +40,9 @@ Quando un timer raggiunge lo zero, viene eseguito il metodo `on_timer`, che va d
|
|||||||
`on_timer` richiede un solo parametro, ovvero la posizione del nodo.
|
`on_timer` richiede un solo parametro, ovvero la posizione del nodo.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("porteautomatiche:porta_aperta", {
|
core.register_node("porteautomatiche:porta_aperta", {
|
||||||
on_timer = function(pos)
|
on_timer = function(pos)
|
||||||
minetest.set_node(pos, { name = "porteautomatiche:porta_chiusa" })
|
core.set_node(pos, { name = "porteautomatiche:porta_chiusa" })
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
@ -60,15 +60,15 @@ Potresti aver tuttavia notato una limitazione: per questioni di ottimizzazione,
|
|||||||
Erba aliena, a scopo illustrativo del capitolo, è un tipo d'erba che ha una probabilità di apparire vicino all'acqua.
|
Erba aliena, a scopo illustrativo del capitolo, è un tipo d'erba che ha una probabilità di apparire vicino all'acqua.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("alieni:erba", {
|
core.register_node("alieni:erba", {
|
||||||
description = "Erba Aliena",
|
description = "Erba Aliena",
|
||||||
light_source = 3, -- Il nodo irradia luce. Min 0, max 14
|
light_source = 3, -- Il nodo irradia luce. Min 0, max 14
|
||||||
tiles = {"alieni_erba.png"},
|
tiles = {"alieni_erba.png"},
|
||||||
groups = {choppy=1},
|
groups = {choppy=1},
|
||||||
on_use = minetest.item_eat(20)
|
on_use = core.item_eat(20)
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_abm({
|
core.register_abm({
|
||||||
nodenames = {"default:dirt_with_grass"}, -- nodo sul quale applicare l'ABM
|
nodenames = {"default:dirt_with_grass"}, -- nodo sul quale applicare l'ABM
|
||||||
neighbors = {"default:water_source", "default:water_flowing"}, -- nodi che devono essere nei suoi dintorni (almeno uno)
|
neighbors = {"default:water_source", "default:water_flowing"}, -- nodi che devono essere nei suoi dintorni (almeno uno)
|
||||||
interval = 10.0, -- viene eseguito ogni 10 secondi
|
interval = 10.0, -- viene eseguito ogni 10 secondi
|
||||||
@ -76,7 +76,7 @@ minetest.register_abm({
|
|||||||
action = function(pos, node, active_object_count,
|
action = function(pos, node, active_object_count,
|
||||||
active_object_count_wider)
|
active_object_count_wider)
|
||||||
local pos = {x = pos.x, y = pos.y + 1, z = pos.z}
|
local pos = {x = pos.x, y = pos.y + 1, z = pos.z}
|
||||||
minetest.set_node(pos, {name = "alieni:erba"})
|
core.set_node(pos, {name = "alieni:erba"})
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
@ -13,7 +13,7 @@ cmd_online:
|
|||||||
Per esempio, il ponte IRC permette ai giocatori di eseguire comandi senza dover entrare in gioco.
|
Per esempio, il ponte IRC permette ai giocatori di eseguire comandi senza dover entrare in gioco.
|
||||||
|
|
||||||
Assicurati quindi di non dar per scontato che un giocatore sia connesso.
|
Assicurati quindi di non dar per scontato che un giocatore sia connesso.
|
||||||
Puoi controllare ciò tramite `minetest.get_player_by_name`, per vedere se ritorna qualcosa o meno.
|
Puoi controllare ciò tramite `core.get_player_by_name`, per vedere se ritorna qualcosa o meno.
|
||||||
|
|
||||||
cb_cmdsprivs:
|
cb_cmdsprivs:
|
||||||
level: warning
|
level: warning
|
||||||
@ -44,7 +44,7 @@ Le mod possono interagire con la chat del giocatore, tra l'inviare messaggi, int
|
|||||||
Per inviare un messaggio a tutti i giocatori connessi in gioco, si usa la funzione `chat_send_all`:
|
Per inviare un messaggio a tutti i giocatori connessi in gioco, si usa la funzione `chat_send_all`:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.chat_send_all("Questo è un messaggio visualizzabile da tutti")
|
core.chat_send_all("Questo è un messaggio visualizzabile da tutti")
|
||||||
```
|
```
|
||||||
|
|
||||||
Segue un esempio di come apparirerebbe in gioco:
|
Segue un esempio di come apparirerebbe in gioco:
|
||||||
@ -60,7 +60,7 @@ Il messaggio appare su una nuova riga, per distinguerlo dai messaggi dei giocato
|
|||||||
Per inviare un messaggio a un giocatore in particolare, si usa invece la funzione `chat_send_player`:
|
Per inviare un messaggio a un giocatore in particolare, si usa invece la funzione `chat_send_player`:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.chat_send_player("Tizio", "Questo è un messaggio per Tizio")
|
core.chat_send_player("Tizio", "Questo è un messaggio per Tizio")
|
||||||
```
|
```
|
||||||
|
|
||||||
Questo messaggio viene mostrato esattamente come il precedente, ma solo, in questo caso, a Tizio.
|
Questo messaggio viene mostrato esattamente come il precedente, ma solo, in questo caso, a Tizio.
|
||||||
@ -70,7 +70,7 @@ Questo messaggio viene mostrato esattamente come il precedente, ma solo, in ques
|
|||||||
Per registrare un comando, per esempio `/foo`, si usa `register_chatcommand`:
|
Per registrare un comando, per esempio `/foo`, si usa `register_chatcommand`:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_chatcommand("foo", {
|
core.register_chatcommand("foo", {
|
||||||
privs = {
|
privs = {
|
||||||
interact = true,
|
interact = true,
|
||||||
},
|
},
|
||||||
@ -160,7 +160,7 @@ Una guida più completa ai pattern è probabilmente quella su [lua-users.org](ht
|
|||||||
Per intercettare un messaggio, si usa `register_on_chat_message`:
|
Per intercettare un messaggio, si usa `register_on_chat_message`:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_chat_message(function(name, message)
|
core.register_on_chat_message(function(name, message)
|
||||||
print(name .. " ha detto " .. message)
|
print(name .. " ha detto " .. message)
|
||||||
return false
|
return false
|
||||||
end)
|
end)
|
||||||
@ -175,10 +175,10 @@ Dovresti assicurarti, poi, che il messaggio potrebbe essere un comando che invia
|
|||||||
o che l'utente potrebbere non avere `shout`.
|
o che l'utente potrebbere non avere `shout`.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_chat_message(function(name, message)
|
core.register_on_chat_message(function(name, message)
|
||||||
if message:sub(1, 1) == "/" then
|
if message:sub(1, 1) == "/" then
|
||||||
print(name .. " ha eseguito un comando")
|
print(name .. " ha eseguito un comando")
|
||||||
elseif minetest.check_player_privs(name, { shout = true }) then
|
elseif core.check_player_privs(name, { shout = true }) then
|
||||||
print(name .. " ha detto " .. message)
|
print(name .. " ha detto " .. message)
|
||||||
else
|
else
|
||||||
print(name .. " ha provato a dire " .. message ..
|
print(name .. " ha provato a dire " .. message ..
|
||||||
|
@ -123,7 +123,7 @@ function indovina.prendi_formspec(nome)
|
|||||||
local formspec = {
|
local formspec = {
|
||||||
"formspec_version[4]",
|
"formspec_version[4]",
|
||||||
"size[6,3.476]",
|
"size[6,3.476]",
|
||||||
"label[0.375,0.5;", minetest.formspec_escape(testo), "]",
|
"label[0.375,0.5;", core.formspec_escape(testo), "]",
|
||||||
"field[0.375,1.25;5.25,0.8;numero;Numero;]",
|
"field[0.375,1.25;5.25,0.8;numero;Numero;]",
|
||||||
"button[1.5,2.3;3,0.8;indovina;Indovina]"
|
"button[1.5,2.3;3,0.8;indovina;Indovina]"
|
||||||
}
|
}
|
||||||
@ -143,10 +143,10 @@ Il metodo principale per farlo è usare `show_formspec`:
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
function indovina.mostra_a(nome)
|
function indovina.mostra_a(nome)
|
||||||
minetest.show_formspec(nome, "indovina:gioco", indovina.prendi_formspec(nome))
|
core.show_formspec(nome, "indovina:gioco", indovina.prendi_formspec(nome))
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_chatcommand("gioco", {
|
core.register_chatcommand("gioco", {
|
||||||
func = function(name)
|
func = function(name)
|
||||||
indovina.mostra_a(name)
|
indovina.mostra_a(name)
|
||||||
end,
|
end,
|
||||||
@ -180,19 +180,19 @@ Per far sì che i formspec siano utili, le informazioni devono essere ritornate
|
|||||||
Il metodo per fare ciò è chiamato Campo di Compilazione (*formspec field submission*), e per `show_formspec` quel campo viene ottenuto usando un callback globale:
|
Il metodo per fare ciò è chiamato Campo di Compilazione (*formspec field submission*), e per `show_formspec` quel campo viene ottenuto usando un callback globale:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
core.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
if formname ~= "indovina:gioco" then
|
if formname ~= "indovina:gioco" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields.indovina then
|
if fields.indovina then
|
||||||
local p_name = player:get_player_name()
|
local p_name = player:get_player_name()
|
||||||
minetest.chat_send_all(p_name .. " ha tentato di indovinare con il numero " .. fields.numero)
|
core.chat_send_all(p_name .. " ha tentato di indovinare con il numero " .. fields.numero)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
La funzione data in `minetest.register_on_player_receive_fields` è chiamata ogni volta che un utente invia un modulo.
|
La funzione data in `core.register_on_player_receive_fields` è chiamata ogni volta che un utente invia un modulo.
|
||||||
La maggior parte dei callback necessiteranno di controllare il nome fornito alla funzione, e uscire se non è quello esatto; tuttavia, alcuni potrebbero necessitare di operare su più moduli, se non addirittura su tutti.
|
La maggior parte dei callback necessiteranno di controllare il nome fornito alla funzione, e uscire se non è quello esatto; tuttavia, alcuni potrebbero necessitare di operare su più moduli, se non addirittura su tutti.
|
||||||
|
|
||||||
Il parametro `fields` è una tabella di tutti i valori inviati dall'utente, indicizzati per stringhe.
|
Il parametro `fields` è una tabella di tutti i valori inviati dall'utente, indicizzati per stringhe.
|
||||||
@ -223,7 +223,7 @@ local function prendi_contesto(nome)
|
|||||||
return contesto
|
return contesto
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_leaveplayer(function(player)
|
core.register_on_leaveplayer(function(player)
|
||||||
_contexts[player:get_player_name()] = nil
|
_contexts[player:get_player_name()] = nil
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
@ -236,7 +236,7 @@ function indovina.mostra_a(nome)
|
|||||||
contesto.soluzione = contesto.soluzione or math.random(1, 10)
|
contesto.soluzione = contesto.soluzione or math.random(1, 10)
|
||||||
|
|
||||||
local formspec = indovina.prendi_formspec(nome, contesto)
|
local formspec = indovina.prendi_formspec(nome, contesto)
|
||||||
minetest.show_formspec(nome, "indovina:gioco", formspec)
|
core.show_formspec(nome, "indovina:gioco", formspec)
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -282,11 +282,11 @@ Ci sono tre diversi modi per far sì che un formspec sia consegnato al client:
|
|||||||
|
|
||||||
### Formspec nei nodi
|
### Formspec nei nodi
|
||||||
|
|
||||||
`minetest.show_formspec` non è l'unico modo per mostrare un formspec; essi possono infatti essere aggiunti anche ai [metadati di un nodo](../map/storage.html).
|
`core.show_formspec` non è l'unico modo per mostrare un formspec; essi possono infatti essere aggiunti anche ai [metadati di un nodo](../map/storage.html).
|
||||||
Per esempio, questo è usato con le casse per permettere tempi più veloci d'apertura - non si ha bisogno di aspettare che il server invii il formspec della cassa al giocatore.
|
Per esempio, questo è usato con le casse per permettere tempi più veloci d'apertura - non si ha bisogno di aspettare che il server invii il formspec della cassa al giocatore.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_node("miamod:tastodestro", {
|
core.register_node("miamod:tastodestro", {
|
||||||
description = "Premimi col tasto destro del mouse!",
|
description = "Premimi col tasto destro del mouse!",
|
||||||
tiles = {"miamod_tastodestro.png"},
|
tiles = {"miamod_tastodestro.png"},
|
||||||
groups = {cracky = 1},
|
groups = {cracky = 1},
|
||||||
@ -295,7 +295,7 @@ minetest.register_node("miamod:tastodestro", {
|
|||||||
-- Il codice che segue imposta il formspec della cassa.
|
-- Il codice che segue imposta il formspec della cassa.
|
||||||
-- I metadati sono un modo per immagazzinare dati nel nodo.
|
-- I metadati sono un modo per immagazzinare dati nel nodo.
|
||||||
|
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = core.get_meta(pos)
|
||||||
meta:set_string("formspec",
|
meta:set_string("formspec",
|
||||||
"formspec_version[4]" ..
|
"formspec_version[4]" ..
|
||||||
"size[5,5]"..
|
"size[5,5]"..
|
||||||
@ -312,7 +312,7 @@ minetest.register_node("miamod:tastodestro", {
|
|||||||
I formspec impostati in questo modo non innescano lo stesso callback.
|
I formspec impostati in questo modo non innescano lo stesso callback.
|
||||||
Per far in modo di ricevere il modulo di input per i formspec nei nodi, bisogna includere una voce `on_receive_fields` al registrare il nodo.
|
Per far in modo di ricevere il modulo di input per i formspec nei nodi, bisogna includere una voce `on_receive_fields` al registrare il nodo.
|
||||||
|
|
||||||
Questo stile di callback viene innescato al premere invio in un campo, che è possibile grazie a `minetest.show_formspec`; tuttavia, questi tipi di moduli possono essere mostrati solo
|
Questo stile di callback viene innescato al premere invio in un campo, che è possibile grazie a `core.show_formspec`; tuttavia, questi tipi di moduli possono essere mostrati solo
|
||||||
tramite il premere col tasto destro del mouse su un nodo. Non è possibile farlo programmaticamente.
|
tramite il premere col tasto destro del mouse su un nodo. Non è possibile farlo programmaticamente.
|
||||||
|
|
||||||
### Inventario del giocatore
|
### Inventario del giocatore
|
||||||
|
@ -79,7 +79,7 @@ Questo permette all'intero pannello di essere ancorato sulla destra della finest
|
|||||||
Puoi creare un elemento HUD una volta ottenuto il riferimento al giocatore al quale assegnarla:
|
Puoi creare un elemento HUD una volta ottenuto il riferimento al giocatore al quale assegnarla:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local giocatore = minetest.get_player_by_name("tizio")
|
local giocatore = core.get_player_by_name("tizio")
|
||||||
local idx = giocatore:hud_add({
|
local idx = giocatore:hud_add({
|
||||||
hud_elem_type = "text",
|
hud_elem_type = "text",
|
||||||
position = {x = 0.5, y = 0.5},
|
position = {x = 0.5, y = 0.5},
|
||||||
@ -268,9 +268,9 @@ function punteggio.aggiorna_hud(giocatore)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_joinplayer(punteggio.aggiorna_hud)
|
core.register_on_joinplayer(punteggio.aggiorna_hud)
|
||||||
|
|
||||||
minetest.register_on_leaveplayer(function(player)
|
core.register_on_leaveplayer(function(player)
|
||||||
hud_salvate[player:get_player_name()] = nil
|
hud_salvate[player:get_player_name()] = nil
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
@ -23,9 +23,9 @@ Per esempio, un valore di 2 sulla gravità, renderà la gravità di un utente du
|
|||||||
Segue l'esempio di un comando di antigravità:
|
Segue l'esempio di un comando di antigravità:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_chatcommand("antigrav", {
|
core.register_chatcommand("antigrav", {
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
local giocatore = minetest.get_player_by_name(name)
|
local giocatore = core.get_player_by_name(name)
|
||||||
giocatore:set_physics_override({
|
giocatore:set_physics_override({
|
||||||
gravity = 0.1, -- imposta la gravità al 10% del suo valore originale
|
gravity = 0.1, -- imposta la gravità al 10% del suo valore originale
|
||||||
-- (0.1 * 9.81)
|
-- (0.1 * 9.81)
|
||||||
|
@ -46,7 +46,7 @@ I privilegi non sono fatti per indicare classi o status.
|
|||||||
Usa `register_privilege` per dichiarare un nuovo privilegio:
|
Usa `register_privilege` per dichiarare un nuovo privilegio:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_privilege("voto", {
|
core.register_privilege("voto", {
|
||||||
description = "Può votare nei sondaggi",
|
description = "Può votare nei sondaggi",
|
||||||
give_to_singleplayer = false
|
give_to_singleplayer = false
|
||||||
})
|
})
|
||||||
@ -59,7 +59,7 @@ minetest.register_privilege("voto", {
|
|||||||
Per controllare velocemente se un giocatore ha tutti i privilegi necessari o meno:
|
Per controllare velocemente se un giocatore ha tutti i privilegi necessari o meno:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local celo, manca = minetest.check_player_privs(player_or_name, {
|
local celo, manca = core.check_player_privs(player_or_name, {
|
||||||
interact = true,
|
interact = true,
|
||||||
voto = true })
|
voto = true })
|
||||||
```
|
```
|
||||||
@ -68,7 +68,7 @@ In quest'esempio, `celo` è true se il giocatore ha sia `interact` che `voto`.
|
|||||||
Se `celo` è false, allora `manca` conterrà una tabella con i privilegi mancanti.
|
Se `celo` è false, allora `manca` conterrà una tabella con i privilegi mancanti.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local celo, manca = minetest.check_player_privs(name, {
|
local celo, manca = core.check_player_privs(name, {
|
||||||
interact = true,
|
interact = true,
|
||||||
voto = true })
|
voto = true })
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ end
|
|||||||
Se non hai bisogno di controllare i privilegi mancanti, puoi inserire `check_player_privs` direttamente nel costrutto if:
|
Se non hai bisogno di controllare i privilegi mancanti, puoi inserire `check_player_privs` direttamente nel costrutto if:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
if not minetest.check_player_privs(name, { interact=true }) then
|
if not core.check_player_privs(name, { interact=true }) then
|
||||||
return false, "Hai bisogno del privilegio 'interact' per eseguire quest'azione!"
|
return false, "Hai bisogno del privilegio 'interact' per eseguire quest'azione!"
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
@ -92,11 +92,11 @@ end
|
|||||||
Si può accedere o modificare i privilegi di un giocatore anche se quest'ultimo non risulta online.
|
Si può accedere o modificare i privilegi di un giocatore anche se quest'ultimo non risulta online.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local privs = minetest.get_player_privs(name)
|
local privs = core.get_player_privs(name)
|
||||||
print(dump(privs))
|
print(dump(privs))
|
||||||
|
|
||||||
privs.voto = true
|
privs.voto = true
|
||||||
minetest.set_player_privs(name, privs)
|
core.set_player_privs(name, privs)
|
||||||
```
|
```
|
||||||
|
|
||||||
I privilegi sono sempre specificati come una tabella chiave-valore, con il loro nome come chiave e true/false come valore.
|
I privilegi sono sempre specificati come una tabella chiave-valore, con il loro nome come chiave e true/false come valore.
|
||||||
|
@ -82,7 +82,7 @@ E hai ragione! L'API di Minetest è molto incentrata sull'Osservatore, per far i
|
|||||||
|
|
||||||
## Modello-Vista-Controllo
|
## Modello-Vista-Controllo
|
||||||
|
|
||||||
Nel prossimo capitolo discuteremo di come testare automaticamente il codice, e uno dei problemi che riscontreremo sarà come separare il più possibile la logica (calcoli, cosa bisognerebbe fare) dalle chiamate alle API (`minetest.*`, altre mod).
|
Nel prossimo capitolo discuteremo di come testare automaticamente il codice, e uno dei problemi che riscontreremo sarà come separare il più possibile la logica (calcoli, cosa bisognerebbe fare) dalle chiamate alle API (`core.*`, altre mod).
|
||||||
|
|
||||||
Un modo per fare ciò è pensare a:
|
Un modo per fare ciò è pensare a:
|
||||||
|
|
||||||
@ -148,14 +148,14 @@ function terreno.mostra_formspec_crea(nome)
|
|||||||
]]
|
]]
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_chatcommand("/land", {
|
core.register_chatcommand("/land", {
|
||||||
privs = { terreno = true },
|
privs = { terreno = true },
|
||||||
func = function(name)
|
func = function(name)
|
||||||
land.gestore_richiesta_crea(name)
|
land.gestore_richiesta_crea(name)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_on_player_receive_fields(function(player,
|
core.register_on_player_receive_fields(function(player,
|
||||||
formname, fields)
|
formname, fields)
|
||||||
terreno.gestore_invio_crea(player:get_player_name(),
|
terreno.gestore_invio_crea(player:get_player_name(),
|
||||||
fields.nome_area)
|
fields.nome_area)
|
||||||
@ -191,7 +191,7 @@ Al contrario, un approccio più comune e leggermente meno rigido è quello API-V
|
|||||||
In un mondo ideale, si avrebbero le 3 aree MVC perfettamente separate... ma siamo nel mondo reale.
|
In un mondo ideale, si avrebbero le 3 aree MVC perfettamente separate... ma siamo nel mondo reale.
|
||||||
Un buon compromesso è ridurre la mod in due parti:
|
Un buon compromesso è ridurre la mod in due parti:
|
||||||
|
|
||||||
* **API** - modello + controllo. Non ci dovrebbe essere nessun uso di `minetest.` nella API.
|
* **API** - modello + controllo. Non ci dovrebbe essere nessun uso di `core.` nella API.
|
||||||
* **Vista** - la vista, esattamente come quella spiegata sopra.
|
* **Vista** - la vista, esattamente come quella spiegata sopra.
|
||||||
È buona norma strutturare questa parte in file separati per ogni tipo di evento.
|
È buona norma strutturare questa parte in file separati per ogni tipo di evento.
|
||||||
|
|
||||||
|
@ -40,11 +40,11 @@ Per esempio, il seguente codice presenta una vulnerabilità che permette ai gioc
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
local function show_formspec(name)
|
local function show_formspec(name)
|
||||||
if not minetest.check_player_privs(name, { privs = true }) then
|
if not core.check_player_privs(name, { privs = true }) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.show_formspec(name, "modman:modman", [[
|
core.show_formspec(name, "modman:modman", [[
|
||||||
size[3,2]
|
size[3,2]
|
||||||
field[0,0;3,1;target;Nome;]
|
field[0,0;3,1;target;Nome;]
|
||||||
button_exit[0,1;3,1;sub;Promuovi]
|
button_exit[0,1;3,1;sub;Promuovi]
|
||||||
@ -52,14 +52,14 @@ local function show_formspec(name)
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_on_player_receive_fields(function(player,
|
core.register_on_player_receive_fields(function(player,
|
||||||
formname, fields)
|
formname, fields)
|
||||||
-- MALE! Manca il controllo dei privilegi!
|
-- MALE! Manca il controllo dei privilegi!
|
||||||
|
|
||||||
local privs = minetest.get_player_privs(fields.target)
|
local privs = core.get_player_privs(fields.target)
|
||||||
privs.kick = true
|
privs.kick = true
|
||||||
privs.ban = true
|
privs.ban = true
|
||||||
minetest.set_player_privs(fields.target, privs)
|
core.set_player_privs(fields.target, privs)
|
||||||
return true
|
return true
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
@ -67,9 +67,9 @@ end)
|
|||||||
Aggiungi un controllo dei privilegi per ovviare:
|
Aggiungi un controllo dei privilegi per ovviare:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_player_receive_fields(function(player,
|
core.register_on_player_receive_fields(function(player,
|
||||||
formname, fields)
|
formname, fields)
|
||||||
if not minetest.check_player_privs(name, { privs = true }) then
|
if not core.check_player_privs(name, { privs = true }) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ inv:set_stack("main", 1, pila)
|
|||||||
Il comportamento dei callback è leggermente più complicato.
|
Il comportamento dei callback è leggermente più complicato.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_item_eat(function(hp_change, replace_with_item,
|
core.register_on_item_eat(function(hp_change, replace_with_item,
|
||||||
itemstack, user, pointed_thing)
|
itemstack, user, pointed_thing)
|
||||||
itemstack:get_meta():set_string("description", "Un po' smangiucchiato")
|
itemstack:get_meta():set_string("description", "Un po' smangiucchiato")
|
||||||
-- Quasi corretto! I dati saranno persi se un altro callback annulla questa chiamata
|
-- Quasi corretto! I dati saranno persi se un altro callback annulla questa chiamata
|
||||||
@ -117,7 +117,7 @@ Se nessun callback cancella l'operazione, la pila sarà impostata e la descrizio
|
|||||||
È meglio quindi fare così:
|
È meglio quindi fare così:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_item_eat(function(hp_change, replace_with_item,
|
core.register_on_item_eat(function(hp_change, replace_with_item,
|
||||||
itemstack, user, pointed_thing)
|
itemstack, user, pointed_thing)
|
||||||
itemstack:get_meta():set_string("description", "Un po' smangiucchiato")
|
itemstack:get_meta():set_string("description", "Un po' smangiucchiato")
|
||||||
user:get_inventory():set_stack("main", user:get_wield_index(),
|
user:get_inventory():set_stack("main", user:get_wield_index(),
|
||||||
|
@ -19,7 +19,6 @@ Dopo aver letto questo libro, se mastichi l'inglese dai un occhio a ciò che seg
|
|||||||
### Programmazione in Lua
|
### Programmazione in Lua
|
||||||
|
|
||||||
* [Programmazione in Lua (PIL)](http://www.lua.org/pil/).
|
* [Programmazione in Lua (PIL)](http://www.lua.org/pil/).
|
||||||
* [Corso accelerato su Lua](http://luatut.com/crash_course.html).
|
|
||||||
|
|
||||||
### Modellazione 3D
|
### Modellazione 3D
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ Qualsiasi utente può inviare qualsiasi formspec con i valori che preferisce qua
|
|||||||
Segue del codice trovato realmente in una mod:
|
Segue del codice trovato realmente in una mod:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_player_receive_fields(function(player,
|
core.register_on_player_receive_fields(function(player,
|
||||||
formname, fields)
|
formname, fields)
|
||||||
for key, field in pairs(fields) do
|
for key, field in pairs(fields) do
|
||||||
local x,y,z = string.match(key,
|
local x,y,z = string.match(key,
|
||||||
@ -71,7 +71,7 @@ Minetest permette alle mod di richiedere ambienti senza limiti, dando loro acces
|
|||||||
Riesci a individuare la vulnerabilità in questo pezzo di codice??
|
Riesci a individuare la vulnerabilità in questo pezzo di codice??
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local ie = minetest.request_insecure_environment()
|
local ie = core.request_insecure_environment()
|
||||||
ie.os.execute(("path/to/prog %d"):format(3))
|
ie.os.execute(("path/to/prog %d"):format(3))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -42,12 +42,12 @@ Minetest ti permette di localizzare i tuoi contenuti in tante lingue diverse, ch
|
|||||||
### Testo formattato
|
### Testo formattato
|
||||||
|
|
||||||
Il server ha bisogno di dire ai client come tradurre il testo.
|
Il server ha bisogno di dire ai client come tradurre il testo.
|
||||||
Questo accade grazie alla funzione `minetest.get_translator(dominiotestuale)`, che abbrevieremo con `S()`:
|
Questo accade grazie alla funzione `core.get_translator(dominiotestuale)`, che abbrevieremo con `S()`:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local S = minetest.get_translator("miamod")
|
local S = core.get_translator("miamod")
|
||||||
|
|
||||||
minetest.register_craftitem("miamod:oggetto", {
|
core.register_craftitem("miamod:oggetto", {
|
||||||
description = S("My Item"),
|
description = S("My Item"),
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@ -57,7 +57,7 @@ Piuttosto che avere tutte le traduzioni di una lingua salvate nello stesso file,
|
|||||||
È buona norma assegnare al dominio testuale lo stesso nome della mod, onde evitare conflitti tra mod diverse.
|
È buona norma assegnare al dominio testuale lo stesso nome della mod, onde evitare conflitti tra mod diverse.
|
||||||
|
|
||||||
Il testo formattato può essere usato nella maggior parte dei casi dove è richiesto un testo fatto per gli esseri umani - come i formspec, i campi di definizioni di un oggetto, `infotext` ecc.
|
Il testo formattato può essere usato nella maggior parte dei casi dove è richiesto un testo fatto per gli esseri umani - come i formspec, i campi di definizioni di un oggetto, `infotext` ecc.
|
||||||
Nel caso dei formspec, tieni presente che dovrai usare la funzione di escape `minetest.formspec_escape` per una corretta visualizzazione.
|
Nel caso dei formspec, tieni presente che dovrai usare la funzione di escape `core.formspec_escape` per una corretta visualizzazione.
|
||||||
|
|
||||||
Quando il client incontra del testo formattato, come quello passato in `description`, ne andrà a cercare il corrispettivo nel file di traduzione della lingua del giocatore. Se la ricerca non avrà avuto esito positivo, ritornerà quello in inglese.
|
Quando il client incontra del testo formattato, come quello passato in `description`, ne andrà a cercare il corrispettivo nel file di traduzione della lingua del giocatore. Se la ricerca non avrà avuto esito positivo, ritornerà quello in inglese.
|
||||||
|
|
||||||
@ -95,8 +95,8 @@ Non è raro dover inserire una variabile dentro una stringa da tradurre.
|
|||||||
Al contrario, dovresti usare il seguente sistema di formattazione:
|
Al contrario, dovresti usare il seguente sistema di formattazione:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_joinplayer(function(player)
|
core.register_on_joinplayer(function(player)
|
||||||
minetest.chat_send_all(S("Everyone, say hi to @1!", player:get_player_name()))
|
core.chat_send_all(S("Everyone, say hi to @1!", player:get_player_name()))
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -130,13 +130,13 @@ local list = {
|
|||||||
S("Potato")
|
S("Potato")
|
||||||
}
|
}
|
||||||
|
|
||||||
minetest.register_chatcommand("find", {
|
core.register_chatcommand("find", {
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
local info = minetest.get_player_information(name)
|
local info = core.get_player_information(name)
|
||||||
local lingua = info and info.language or "en"
|
local lingua = info and info.language or "en"
|
||||||
|
|
||||||
for _, riga in ipairs(lista) do
|
for _, riga in ipairs(lista) do
|
||||||
local trad = minetest.get_translated_string(language, riga)
|
local trad = core.get_translated_string(language, riga)
|
||||||
if trad:contains(query) then
|
if trad:contains(query) then
|
||||||
return riga
|
return riga
|
||||||
end
|
end
|
||||||
|
@ -52,7 +52,7 @@ Quello che fa è cercare i file Lua con il nome che termina in `_spec`, eseguend
|
|||||||
```lua
|
```lua
|
||||||
miamod = {}
|
miamod = {}
|
||||||
|
|
||||||
dofile(minetest.get_modpath("miamod") .. "/api.lua")
|
dofile(core.get_modpath("miamod") .. "/api.lua")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ _G.minetest = {}
|
|||||||
|
|
||||||
-- Definisce la funzione simulata
|
-- Definisce la funzione simulata
|
||||||
local chiamate_chat_send_all = {}
|
local chiamate_chat_send_all = {}
|
||||||
function minetest.chat_send_all(name, message)
|
function core.chat_send_all(name, message)
|
||||||
table.insert(chiamate_chat_send_all, { nome = name, messaggio = message })
|
table.insert(chiamate_chat_send_all, { nome = name, messaggio = message })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ layout: compress
|
|||||||
<html>
|
<html>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<head>
|
<head>
|
||||||
<title>{% if page.homepage %}{% else %}{{ page.title }} - {% endif %}Minetest Modding Book</title>
|
<title>{% if page.homepage %}{% else %}{{ page.title }} - {% endif %}Luanti / Minetest Modding Book</title>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="author" content="rubenwardy">
|
<meta name="author" content="rubenwardy">
|
||||||
@ -22,7 +22,7 @@ layout: compress
|
|||||||
<meta name="og:url" content="https://rubenwardy.com/minetest_modding_book{{ page.url }}">
|
<meta name="og:url" content="https://rubenwardy.com/minetest_modding_book{{ page.url }}">
|
||||||
<meta name="og:title" content="{{ page.title | escape }}">
|
<meta name="og:title" content="{{ page.title | escape }}">
|
||||||
<meta name="og:author" content="rubenwardy">
|
<meta name="og:author" content="rubenwardy">
|
||||||
<meta name="og:site_name" content="Minetest Modding Book">
|
<meta name="og:site_name" content="Luanti Modding Book (formerly Minetest)">
|
||||||
{% if page.description %}
|
{% if page.description %}
|
||||||
<meta name="og:description" content="{{ page.description | escape | strip }}">
|
<meta name="og:description" content="{{ page.description | escape | strip }}">
|
||||||
<meta name="description" content="{{ page.description | escape | strip }}">
|
<meta name="description" content="{{ page.description | escape | strip }}">
|
||||||
|
@ -8,7 +8,7 @@ noindex: true
|
|||||||
|
|
||||||
<main>
|
<main>
|
||||||
<article>
|
<article>
|
||||||
<h1>Minetest Modding Book</h1>
|
<h1>Luanti Modding Book (formerly Minetest)</h1>
|
||||||
|
|
||||||
<h2>Thanks for sharing your feedback!</h2>
|
<h2>Thanks for sharing your feedback!</h2>
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ layout: none
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Minetest Modding Book</title>
|
<title>Luanti Modding Book (formerly Minetest)</title>
|
||||||
<meta name="og:description" content="An easy guide to learn how to create mods for Minetest">
|
<meta name="og:description" content="An easy guide to learn how to create mods for Minetest">
|
||||||
<meta name="description" content="An easy guide to learn how to create mods for Minetest">
|
<meta name="description" content="An easy guide to learn how to create mods for Minetest">
|
||||||
<link rel="canonical" href="https://rubenwardy.com/minetest_modding_book/">
|
<link rel="canonical" href="https://rubenwardy.com/minetest_modding_book/">
|
||||||
@ -28,11 +28,11 @@ layout: none
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main>
|
<main>
|
||||||
<h1>Minetest Modding Book</h1>
|
<h1>Luanti Modding Book (formerly Minetest)</h1>
|
||||||
<p>An easy guide to learn how to create mods for Minetest.</p>
|
<p>An easy guide to learn how to create mods for Minetest.</p>
|
||||||
<p>Detecting and redirecting to the correct translation.</p>
|
<p>Detecting and redirecting to the correct translation.</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="en/index.html">View Minetest Modding Book in English</a>
|
<a href="en/index.html">View Luanti Modding Book in English</a>
|
||||||
</p>
|
</p>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
|
@ -6,7 +6,7 @@ root: .
|
|||||||
|
|
||||||
<main>
|
<main>
|
||||||
<article>
|
<article>
|
||||||
<h1>Minetest Modding Book</h1>
|
<h1>Luanti Modding Book (formerly Minetest)</h1>
|
||||||
|
|
||||||
<h2>Choose a Language</h2>
|
<h2>Choose a Language</h2>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user