From d7465a72d247e8324fb2cab42e8d03002d0c5296 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Wed, 21 Feb 2018 00:38:18 +0000 Subject: [PATCH] Basic Map Operations: Add chapter --- _data/links_en.yml | 30 +++--- en/chapters/environment.md | 196 +++++++++++++++++++++++++++++++++++++ 2 files changed, 213 insertions(+), 13 deletions(-) create mode 100644 en/chapters/environment.md diff --git a/_data/links_en.yml b/_data/links_en.yml index 25668ff..781e72c 100644 --- a/_data/links_en.yml +++ b/_data/links_en.yml @@ -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 diff --git a/en/chapters/environment.md b/en/chapters/environment.md new file mode 100644 index 0000000..c48ee26 --- /dev/null +++ b/en/chapters/environment.md @@ -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. + + + + + + +## 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. + +
+

To Do

+ + This section will be added soon™. +
+ +