Basic Map Operations: Add chapter
This commit is contained in:
parent
7760bffab2
commit
d7465a72d2
@ -27,62 +27,66 @@
|
||||
|
||||
- hr: true
|
||||
|
||||
- title: Node Metadata
|
||||
- title: Basic Map Operations
|
||||
num: 6
|
||||
link: chapters/node_metadata.html
|
||||
link: chapters/environment.html
|
||||
|
||||
- title: Active Block Modifiers
|
||||
num: 7
|
||||
link: chapters/abms.html
|
||||
|
||||
- title: Node Metadata
|
||||
num: 8
|
||||
link: chapters/node_metadata.html
|
||||
|
||||
- hr: true
|
||||
|
||||
- title: Privileges
|
||||
num: 8
|
||||
num: 9
|
||||
link: chapters/privileges.html
|
||||
|
||||
- title: Chat and Commands
|
||||
num: 9
|
||||
num: 10
|
||||
link: chapters/chat.html
|
||||
|
||||
- title: Complex Chat Commands
|
||||
num: 10
|
||||
num: 11
|
||||
link: chapters/chat_complex.html
|
||||
|
||||
- title: Player Physics
|
||||
num: 11
|
||||
num: 12
|
||||
link: chapters/player_physics.html
|
||||
|
||||
- title: Formspecs
|
||||
num: 12
|
||||
num: 13
|
||||
link: chapters/formspecs.html
|
||||
|
||||
- title: HUD
|
||||
num: 13
|
||||
num: 14
|
||||
link: chapters/hud.html
|
||||
|
||||
- title: "SFINV: Inventory Formspec"
|
||||
num: 14
|
||||
num: 15
|
||||
link: chapters/sfinv.html
|
||||
|
||||
- hr: true
|
||||
|
||||
- title: ItemStacks
|
||||
num: 15
|
||||
num: 16
|
||||
link: chapters/itemstacks.html
|
||||
|
||||
- title: Inventories
|
||||
num: 16
|
||||
num: 17
|
||||
link: chapters/inventories.html
|
||||
|
||||
- hr: true
|
||||
|
||||
- title: Releasing a Mod
|
||||
num: 17
|
||||
num: 18
|
||||
link: chapters/releasing.html
|
||||
|
||||
- title: Read More
|
||||
num: 18
|
||||
num: 19
|
||||
link: chapters/readmore.html
|
||||
|
||||
- hr: true
|
||||
|
196
en/chapters/environment.md
Normal file
196
en/chapters/environment.md
Normal file
@ -0,0 +1,196 @@
|
||||
---
|
||||
title: Basic Map Operations
|
||||
layout: default
|
||||
root: ../../
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
In this chapter you will learn how to perform basic actions on the map.
|
||||
|
||||
* [Map Structure](#map-structure)
|
||||
* [Reading](#reading)
|
||||
* [Reading nodes](#reading-nodes)
|
||||
* [Finding nodes](#finding-nodes)
|
||||
* [Writing](#writing)
|
||||
* [Loading and Deleting](#loading-and-deleting)
|
||||
|
||||
## Map Structure
|
||||
|
||||
The Minetest map is split into MapBlocks, each MapBlocks being a cube of size 16.
|
||||
As players travel around the map, MapBlocks are created, loaded, and unloaded.
|
||||
Areas of the map which are not yet loaded are full of *ignore* nodes, an impassable
|
||||
unselectable placeholder node. Empty space is full of *air* nodes, an invisible node
|
||||
you can walk through.
|
||||
|
||||
Loaded map blocks are often refered to as *active blocks*. Active Blocks can be
|
||||
read from or written to by mods or players, have active entities. The Engine also
|
||||
performs operations on the map, such as performing liquid physics.
|
||||
|
||||
MapBlocks can either be loaded from the world database or generated. MapBlocks
|
||||
will be generated up to the map generation limit (`mapgen_limit`) which is set
|
||||
at its maximum value, 31000, by default. Existing MapBlocks can however be
|
||||
loaded from the world database outside of the generation limit.
|
||||
|
||||
|
||||
<!--Multiple MapBlocks are generated at a time in groups called *MapChunks*. Each
|
||||
MapChunk is by default 5x5x5<sup>1</sup> MapBlocks, which is 80x80x80 nodes.
|
||||
The size of a MapChunk can change using the chunk_size setting but will always
|
||||
be a cube. -->
|
||||
|
||||
|
||||
|
||||
## Reading
|
||||
|
||||
### Reading nodes
|
||||
|
||||
You can read from the map once you have a position:
|
||||
|
||||
{% highlight lua %}
|
||||
local node = minetest.get_node({ x = 1, y = 3, z = 4 })
|
||||
print(dump(node)) --> { name=.., param1=.., param2=.. }
|
||||
{% endhighlight %}
|
||||
|
||||
If the position is a decimal, it will be rounded to the containing node.
|
||||
The function will always return a table containing the node information:
|
||||
|
||||
* `name` - The node name, will be ignore when the area is unloaded.
|
||||
* `param1` - See the node definition, will commonly be light.
|
||||
* `param2` - See the node definition.
|
||||
|
||||
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`.
|
||||
|
||||
You can use `minetest.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.
|
||||
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
|
||||
limit (`mapgen_limit`).
|
||||
|
||||
### Finding nodes
|
||||
|
||||
Minetest offers a number of helper functions to speed up common map actions.
|
||||
The most commonly used of these are for finding nodes.
|
||||
|
||||
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,
|
||||
and adapt the growth rate accordingly.
|
||||
|
||||
{% highlight lua %}
|
||||
local grow_speed = 1
|
||||
local node_pos = minetest.find_node_near(pos, 5, { "default:mese" })
|
||||
if node_pos then
|
||||
minetest.chat_send_all("Node found at: " .. dump(node_pos))
|
||||
grow_speed = 2
|
||||
end
|
||||
{% endhighlight %}
|
||||
|
||||
Lets say, for example, that the growth rate increases the more mese there is
|
||||
nearby. You should then use a function which can find multiple nodes in area:
|
||||
|
||||
{% highlight lua %}
|
||||
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
||||
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
||||
local pos_list = minetest.find_nodes_in_area(pos1, pos2, { "default:mese" })
|
||||
local grow_speed = 1 + #pos_list
|
||||
{% endhighlight %}
|
||||
|
||||
The above code doesn't quite do what we want, as it checks based on area, whereas
|
||||
`find_node_near` checks based on range. In order to fix this we will,
|
||||
unfortunately, need to manually check the range ourselves.
|
||||
|
||||
{% highlight lua %}
|
||||
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
||||
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
||||
local pos_list = minetest.find_nodes_in_area(pos1, pos2, { "default:mese" })
|
||||
local grow_speed = 1
|
||||
for i=1, #pos_list do
|
||||
local delta = vector.subtract(pos_list[i], pos)
|
||||
if delta.x*delta.x + delta.y*delta.y <= 5*5 then
|
||||
grow_speed = grow_speed + 1
|
||||
end
|
||||
end
|
||||
{% endhighlight %}
|
||||
|
||||
Now your code will correctly increase `grow_speed` based on mese nodes in range.
|
||||
Note how we compared the squared distance from the position, rather than square
|
||||
rooting it to obtain the actual distance. This is because computers find square
|
||||
roots computationally expensive, so you should avoid them as much as possible.
|
||||
|
||||
There are more variations of the above two functions, such as
|
||||
`find_nodes_with_meta` and `find_nodes_in_area_under_air`, which work in a
|
||||
similar way and are useful in other circumstances.
|
||||
|
||||
## Writing
|
||||
|
||||
### Writing nodes
|
||||
|
||||
You can use `set_node` to write to the map. Each call to set_node will cause
|
||||
lighting to be recalculated, which means that set_node is fairly slow for large
|
||||
numbers of nodes.
|
||||
|
||||
{% highlight lua %}
|
||||
minetest.set_node({ x = 1, y = 3, z = 4 }, { name = "default:mese" })
|
||||
|
||||
local node = minetest.get_node({ x = 1, y = 3, z = 4 })
|
||||
print(node.name) --> default:mese
|
||||
{% endhighlight %}
|
||||
|
||||
|
||||
### Moving and swapping nodes
|
||||
|
||||
Moving a node is the same as swapping a node, except that one of the nodes
|
||||
becomes air.
|
||||
Here is a naive example to move a node:
|
||||
|
||||
{% highlight lua %}
|
||||
-- DO NOT ACTUALLY USE THIS
|
||||
local pos1 = { x = 1, y = 3, z = 4 }
|
||||
local pos2 = vector.add(pos, { x = 1, y = 0, z = 0 })
|
||||
local node1 = minetest.get_node(pos1)
|
||||
local node2 = minetest.get_node(pos2)
|
||||
minetest.set_node(pos1, node2)
|
||||
minetest.set_node(pos2, node1)
|
||||
-- DO NOT ACTUALLY USE THIS
|
||||
{% endhighlight %}
|
||||
|
||||
This won't copy any node meta data to the new position, or delete the old meta
|
||||
data. Luckily Minetest has a function which you can use instead of the above:
|
||||
|
||||
{% highlight lua %}
|
||||
minetest.swap_node(pos, vector.add(pos, { x = 1, y = 0, z = 0 }))
|
||||
{% endhighlight %}
|
||||
|
||||
### Removing nodes
|
||||
|
||||
A node must always be present. When someone says to remove a node, what
|
||||
is usually meant is they want to set the node to `air`.
|
||||
|
||||
The following two lines will both remove a node, and are both identical:
|
||||
|
||||
{% highlight lua %}
|
||||
minetest.remove_node(pos)
|
||||
minetest.set_node(pos, { name = "air" })
|
||||
{% endhighlight %}
|
||||
|
||||
## Loading and Deleting
|
||||
|
||||
You can use `minetest.emerge_area` and `minetest.delete_area` to load
|
||||
and delete map blocks.
|
||||
|
||||
<div class="notice">
|
||||
<h2>To Do</h2>
|
||||
|
||||
This section will be added soon™.
|
||||
</div>
|
||||
|
||||
<!--
|
||||
## Efficient Bulk Operations
|
||||
## To Do
|
||||
|
||||
* line_of_sight
|
||||
* raycast
|
||||
* dig_node
|
||||
* place_node
|
||||
* punch_node
|
||||
-->
|
Loading…
Reference in New Issue
Block a user