Basic Map Operations: Finish chapter
This commit is contained in:
parent
d7465a72d2
commit
ad76b127dd
@ -10,10 +10,13 @@ In this chapter you will learn how to perform basic actions on the map.
|
|||||||
|
|
||||||
* [Map Structure](#map-structure)
|
* [Map Structure](#map-structure)
|
||||||
* [Reading](#reading)
|
* [Reading](#reading)
|
||||||
* [Reading nodes](#reading-nodes)
|
* [Reading Nodes](#reading-nodes)
|
||||||
* [Finding nodes](#finding-nodes)
|
* [Finding Nodes](#finding-nodes)
|
||||||
* [Writing](#writing)
|
* [Writing](#writing)
|
||||||
* [Loading and Deleting](#loading-and-deleting)
|
* [Writing Nodes](#writing-nodes)
|
||||||
|
* [Removing Nodes](#removing-nodes)
|
||||||
|
* [Loading Blocks](#loading-blocks)
|
||||||
|
* [Deleting Blocks](#deleting-blocks)
|
||||||
|
|
||||||
## Map Structure
|
## Map Structure
|
||||||
|
|
||||||
@ -42,7 +45,7 @@ be a cube. -->
|
|||||||
|
|
||||||
## Reading
|
## Reading
|
||||||
|
|
||||||
### Reading nodes
|
### Reading Nodes
|
||||||
|
|
||||||
You can read from the map once you have a position:
|
You can read from the map once you have a position:
|
||||||
|
|
||||||
@ -67,7 +70,7 @@ 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
|
||||||
limit (`mapgen_limit`).
|
limit (`mapgen_limit`).
|
||||||
|
|
||||||
### Finding nodes
|
### Finding Nodes
|
||||||
|
|
||||||
Minetest offers a number of helper functions to speed up common map actions.
|
Minetest offers a number of helper functions to speed up common map actions.
|
||||||
The most commonly used of these are for finding nodes.
|
The most commonly used of these are for finding nodes.
|
||||||
@ -123,7 +126,7 @@ similar way and are useful in other circumstances.
|
|||||||
|
|
||||||
## Writing
|
## Writing
|
||||||
|
|
||||||
### Writing nodes
|
### Writing Nodes
|
||||||
|
|
||||||
You can use `set_node` to write to the map. Each call to set_node will cause
|
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
|
lighting to be recalculated, which means that set_node is fairly slow for large
|
||||||
@ -136,32 +139,19 @@ local node = minetest.get_node({ x = 1, y = 3, z = 4 })
|
|||||||
print(node.name) --> default:mese
|
print(node.name) --> default:mese
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
|
set_node will remove any associated meta data or inventory from that position.
|
||||||
|
This isn't desirable in all circumstances, especially if you're using multiple
|
||||||
|
node definitions to represent one conceptual node. An example of this is the
|
||||||
|
furnace node - whilst you think conceptually of it as one node, it's actually
|
||||||
|
two.
|
||||||
|
|
||||||
### Moving and swapping nodes
|
You can set a node without deleting meta data or the inventory like so:
|
||||||
|
|
||||||
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 %}
|
{% highlight lua %}
|
||||||
-- DO NOT ACTUALLY USE THIS
|
minetest.swap_node({ x = 1, y = 3, z = 4 }, { name = "default:mese" })
|
||||||
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 %}
|
{% endhighlight %}
|
||||||
|
|
||||||
This won't copy any node meta data to the new position, or delete the old meta
|
### Removing Nodes
|
||||||
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
|
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`.
|
is usually meant is they want to set the node to `air`.
|
||||||
@ -173,24 +163,65 @@ minetest.remove_node(pos)
|
|||||||
minetest.set_node(pos, { name = "air" })
|
minetest.set_node(pos, { name = "air" })
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
## Loading and Deleting
|
In fact, remove_node will call set_node with name being air.
|
||||||
|
|
||||||
You can use `minetest.emerge_area` and `minetest.delete_area` to load
|
## Loading Blocks
|
||||||
and delete map blocks.
|
|
||||||
|
|
||||||
<div class="notice">
|
You can use `minetest.emerge_area` load map blocks. Emerge area is asynchronous,
|
||||||
<h2>To Do</h2>
|
meaning the the blocks won't be loaded instantly. Instead they will be loaded
|
||||||
|
soon in the future, and the callback will be called each time.
|
||||||
|
|
||||||
This section will be added soon™.
|
{% highlight lua %}
|
||||||
</div>
|
-- Load a 20x20x20 area
|
||||||
|
local halfsize = { x = 10, y = 10, z = 10 }
|
||||||
|
local pos1 = vector.subtract(pos, halfsize)
|
||||||
|
local pos2 = vector.add (pos, halfsize)
|
||||||
|
|
||||||
<!--
|
local context = {} -- persist data between callback calls
|
||||||
## Efficient Bulk Operations
|
minetest.emerge_area(pos1, pos2, emerge_callback, context)
|
||||||
## To Do
|
{% endhighlight %}
|
||||||
|
|
||||||
* line_of_sight
|
Minetest will call `emerge_callback` whenever it loads a block, with some
|
||||||
* raycast
|
progress information.
|
||||||
* dig_node
|
|
||||||
* place_node
|
{% highlight lua %}
|
||||||
* punch_node
|
local function emerge_callback(pos, action, num_calls_remaining, context)
|
||||||
-->
|
-- On first call, record number of blocks
|
||||||
|
if not context.total_blocks then
|
||||||
|
context.total_blocks = num_calls_remaining + 1
|
||||||
|
context.loaded_blocks = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Increment number of blocks loaded
|
||||||
|
context.loaded_blocks = context.loaded_blocks + 1
|
||||||
|
|
||||||
|
-- Send progress message
|
||||||
|
if context.total_blocks == context.loaded_blocks then
|
||||||
|
minetest.chat_send_all("Finished loading blocks!")
|
||||||
|
end
|
||||||
|
local perc = 100 * context.loaded_blocks / context.total_blocks
|
||||||
|
minetest.chat_send_all(string.format("Loading blocks %d/%d (%.2f%%)",
|
||||||
|
context.loaded_blocks, context.total_blocks, perc)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
This is not the only way of loading blocks; Using a LVM will also cause the
|
||||||
|
encompassed blocks to be loaded synchronously.
|
||||||
|
|
||||||
|
## Deleting Blocks
|
||||||
|
|
||||||
|
You can use delete_blocks to delete a range of map blocks:
|
||||||
|
|
||||||
|
{% highlight lua %}
|
||||||
|
-- Delete a 20x20x20 area
|
||||||
|
local halfsize = { x = 10, y = 10, z = 10 }
|
||||||
|
local pos1 = vector.subtract(pos, halfsize)
|
||||||
|
local pos2 = vector.add (pos, halfsize)
|
||||||
|
|
||||||
|
minetest.delete_area(pos1, pos2)
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
This will delete all map blocks in that area, *inclusive*. This means that some
|
||||||
|
nodes will be deleted outside the are as they will be on a mapblock which overlaps
|
||||||
|
the area bounds.
|
||||||
|
Loading…
Reference in New Issue
Block a user