mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
Improve LuaVoxelManip documentation
This commit is contained in:
parent
2a12579fab
commit
f9e394a466
@ -4,6 +4,11 @@
|
||||
-- Constants values for use with the Lua API
|
||||
--
|
||||
|
||||
-- Built-in Content IDs (for use with VoxelManip API)
|
||||
core.CONTENT_UNKNOWN = 125
|
||||
core.CONTENT_AIR = 126
|
||||
core.CONTENT_IGNORE = 127
|
||||
|
||||
-- Block emerge status constants (for use with core.emerge_area)
|
||||
core.EMERGE_CANCELLED = 0
|
||||
core.EMERGE_ERRORED = 1
|
||||
|
167
doc/lua_api.txt
167
doc/lua_api.txt
@ -2812,22 +2812,171 @@ nil, this table will be used to store the result instead of creating a new table
|
||||
`noisevals = noise:getMapSlice({x=24, z=1}, {x=1, z=1})`
|
||||
|
||||
### `VoxelManip`
|
||||
An interface to the `MapVoxelManipulator` for Lua.
|
||||
|
||||
It can be created via `VoxelManip()` or `minetest.get_voxel_manip()`.
|
||||
The map will be pre-loaded if two positions are passed to either.
|
||||
#### About VoxelManip
|
||||
VoxelManip is a scripting interface to the internal 'Map Voxel Manipulator' facility. The purpose of
|
||||
this object is for fast, low-level, bulk access to reading and writing Map content. As such, setting
|
||||
map nodes through VoxelManip will lack many of the higher level features and concepts you may be used
|
||||
to with other methods of setting nodes. For example, nodes will not have their construction and
|
||||
destruction callbacks run, and no rollback information is logged.
|
||||
|
||||
It is important to note that VoxelManip is designed for speed, and *not* ease of use or flexibility.
|
||||
If your mod requires a map manipulation facility that will handle 100% of all edge cases, or the use
|
||||
of high level node placement features, perhaps minetest.set_node() is better suited for the job.
|
||||
|
||||
In addition, VoxelManip might not be faster, or could even be slower, for your specific use case.
|
||||
VoxelManip is most effective when setting very large areas of map at once - for example, if only
|
||||
setting a 5x5x5 node area, a minetest.set_node() loop may be more optimal. Always profile code
|
||||
using both methods of map manipulation to determine which is most appropriate for your usage.
|
||||
|
||||
#### Using VoxelManip
|
||||
A VoxelManip object can be created any time using either:
|
||||
`VoxelManip([p1, p2])`, or `minetest.get_voxel_manip([p1, p2])`.
|
||||
|
||||
If the optional position parameters are present for either of these routines, the specified region
|
||||
will be pre-loaded into the VoxelManip object on creation. Otherwise, the area of map you wish to
|
||||
manipulate must first be loaded into the VoxelManip object using `VoxelManip:read_from_map()`.
|
||||
|
||||
Note that `VoxelManip:read_from_map()` returns two position vectors. The region formed by these
|
||||
positions indicate the minimum and maximum (respectively) positions of the area actually loaded in
|
||||
the VoxelManip, which may be larger than the area requested. For convenience, the loaded area
|
||||
coordinates can also be queried any time after loading map data with `VoxelManip:get_emerged_area()`.
|
||||
|
||||
Now that the VoxelManip object is populated with map data, your mod can fetch a copy of this data
|
||||
using either of two methods. `VoxelManip:get_node_at()`, which retrieves an individual node in a
|
||||
MapNode formatted table at the position requested is the simplest method to use, but also the slowest.
|
||||
|
||||
Nodes in a VoxelManip object may also be read in bulk to a flat array table using:
|
||||
`VoxelManip:get_data()` for node content (in Content ID form, see section 'Content IDs'),
|
||||
`VoxelManip:get_light_data()` for node light levels, and
|
||||
`VoxelManip:get_param2_data()` for the node type-dependent "param2" values.
|
||||
|
||||
See section 'Flat array format' for more details.
|
||||
|
||||
It is very important to understand that the tables returned by any of the above three functions
|
||||
represent a snapshot of the VoxelManip's internal state at the time of the call. This copy of the
|
||||
data will *not* magically update itself if another function modifies the internal VoxelManip state.
|
||||
Any functions that modify a VoxelManip's contents work on the VoxelManip's internal state unless
|
||||
otherwise explicitly stated.
|
||||
|
||||
Once the bulk data has been edited to your liking, the internal VoxelManip state can be set using:
|
||||
`VoxelManip:set_data()` for node content (in Content ID form, see section 'Content IDs'),
|
||||
`VoxelManip:set_light_data()` for node light levels, and
|
||||
`VoxelManip:set_param2_data()` for the node type-dependent "param2" values.
|
||||
|
||||
The parameter to each of the above three functions can use any table at all in the same flat array
|
||||
format as produced by get_data() et al. and is *not required* to be a table retrieved from get_data().
|
||||
|
||||
Once the internal VoxelManip state has been modified to your liking, the changes can be committed back
|
||||
to the map by calling `VoxelManip:write_to_map()`.
|
||||
|
||||
Finally, a call to `VoxelManip:update_map()` is required to re-calculate lighting and set the blocks
|
||||
as being modified so that connected clients are sent the updated parts of map.
|
||||
|
||||
|
||||
##### Flat array format
|
||||
Let
|
||||
`Nx = p2.X - p1.X + 1`,
|
||||
`Ny = p2.Y - p1.Y + 1`, and
|
||||
`Nz = p2.Z - p1.Z + 1`.
|
||||
|
||||
Then, for a loaded region of p1..p2, this array ranges from `1` up to and including the value of
|
||||
the expression `Nx * Ny * Nz`.
|
||||
|
||||
Positions offset from p1 are present in the array with the format of:
|
||||
```
|
||||
[
|
||||
(0, 0, 0), (1, 0, 0), (2, 0, 0), ... (Nx, 0, 0),
|
||||
(0, 1, 0), (1, 1, 0), (2, 1, 0), ... (Nx, 1, 0),
|
||||
...
|
||||
(0, Ny, 0), (1, Ny, 0), (2, Ny, 0), ... (Nx, Ny, 0),
|
||||
(0, 0, 1), (1, 0, 1), (2, 0, 1), ... (Nx, 0, 1),
|
||||
...
|
||||
(0, Ny, 2), (1, Ny, 2), (2, Ny, 2), ... (Nx, Ny, 2),
|
||||
...
|
||||
(0, Ny, Nz), (1, Ny, Nz), (2, Ny, Nz), ... (Nx, Ny, Nz)
|
||||
]
|
||||
```
|
||||
|
||||
and the array index for a position p contained completely in p1..p2 is:
|
||||
|
||||
`(p.Z - p1.Z) * Ny * Nx + (p.Y - p1.Y) * Nx + (p.X - p1.X) + 1`
|
||||
|
||||
Note that this is the same "flat 3D array" format as `PerlinNoiseMap:get3dMap_flat()`.
|
||||
VoxelArea objects (see section 'VoxelArea') can be used to simplify calculation of the index
|
||||
for a single point in a flat VoxelManip array.
|
||||
|
||||
##### Content IDs
|
||||
A Content ID is a unique integer identifier for a specific node type. These IDs are used by VoxelManip
|
||||
in place of the node name string for `VoxelManip:get_data()` and `VoxelManip:set_data()`. You can use
|
||||
`minetest.get_content_id()` to look up the Content ID for the specified node name, and
|
||||
`minetest.get_name_from_content_id()` to look up the node name string for a given Content ID.
|
||||
After registration of a node, its Content ID will remain the same throughout execution of the mod.
|
||||
Note that the node being queried needs to have already been been registered.
|
||||
|
||||
The following builtin node types have their Content IDs defined as constants:
|
||||
```
|
||||
core.CONTENT_UNKNOWN (ID for "unknown" nodes)
|
||||
core.CONTENT_AIR (ID for "air" nodes)
|
||||
core.CONTENT_IGNORE (ID for "ignore" nodes)
|
||||
```
|
||||
|
||||
##### Mapgen VoxelManip objects
|
||||
Inside of `on_generated()` callbacks, it is possible to retrieve the same VoxelManip object used by the
|
||||
core's Map Generator (commonly abbreviated Mapgen). Most of the rules previously described still apply
|
||||
but with a few differences:
|
||||
* The Mapgen VoxelManip object is retrieved using: `minetest.get_mapgen_object("voxelmanip")`
|
||||
* This VoxelManip object already has the region of map just generated loaded into it; it's not necessary
|
||||
to call `VoxelManip:read_from_map()` before using a Mapgen VoxelManip.
|
||||
* The `on_generated()` callbacks of some mods may place individual nodes in the generated area using
|
||||
non-VoxelManip map modification methods. Because the same Mapgen VoxelManip object is passed through
|
||||
each `on_generated()` callback, it becomes necessary for the Mapgen VoxelManip object to maintain
|
||||
consistency with the current map state. For this reason, calling any of the following functions:
|
||||
`minetest.add_node()`, `minetest.set_node()`, or `minetest.swap_node()`
|
||||
will also update the Mapgen VoxelManip object's internal state active on the current thread.
|
||||
* After modifying the Mapgen VoxelManip object's internal buffer, it may be necessary to update lighting
|
||||
information using either: `VoxelManip:calc_lighting()` or `VoxelManip:set_lighting()`.
|
||||
* `VoxelManip:update_map()` does not need to be called after `write_to_map()`. The map update is performed
|
||||
automatically after all on_generated callbacks have been run for that generated block.
|
||||
|
||||
##### Other API functions operating on a VoxelManip
|
||||
If any VoxelManip contents were set to a liquid node, `VoxelManip:update_liquids()` must be called
|
||||
for these liquid nodes to begin flowing. It is recommended to call this function only after having
|
||||
written all buffered data back to the VoxelManip object, save for special situations where the modder
|
||||
desires to only have certain liquid nodes begin flowing.
|
||||
|
||||
The functions `minetest.generate_ores()` and `minetest.generate_decorations()` will generate all
|
||||
registered decorations and ores throughout the full area inside of the specified VoxelManip object.
|
||||
|
||||
`minetest.place_schematic_on_vmanip()` is otherwise identical to `minetest.place_schematic()`,
|
||||
except instead of placing the specified schematic directly on the map at the specified position, it
|
||||
will place the schematic inside of the VoxelManip.
|
||||
|
||||
##### Notes
|
||||
* Attempting to read data from a VoxelManip object before map is read will result in a zero-length
|
||||
array table for `VoxelManip:get_data()`, and an "ignore" node at any position for
|
||||
`VoxelManip:get_node_at()`.
|
||||
* If either a region of map has not yet been generated or is out-of-bounds of the map, that region is
|
||||
filled with "ignore" nodes.
|
||||
* Other mods, or the core itself, could possibly modify the area of map currently loaded into a VoxelManip
|
||||
object. With the exception of Mapgen VoxelManips (see above section), the internal buffers are not
|
||||
updated. For this reason, it is strongly encouraged to complete the usage of a particular VoxelManip
|
||||
object in the same callback it had been created.
|
||||
* If a VoxelManip object will be used often, such as in an `on_generated()` callback, consider passing
|
||||
a file-scoped table as the optional parameter to `VoxelManip:get_data()`, which serves as a static
|
||||
buffer the function can use to write map data to instead of returning a new table each call. This
|
||||
greatly enhances performance by avoiding unnecessary memory allocations.
|
||||
|
||||
#### Methods
|
||||
* `read_from_map(p1, p2)`: Reads a chunk of map from the map containing the
|
||||
region formed by `p1` and `p2`.
|
||||
* `read_from_map(p1, p2)`: Loads a chunk of map into the VoxelManip object containing
|
||||
the region formed by `p1` and `p2`.
|
||||
* returns actual emerged `pmin`, actual emerged `pmax`
|
||||
* `write_to_map()`: Writes the data loaded from the `VoxelManip` back to the map.
|
||||
* **important**: data must be set using `VoxelManip:set_data` before calling this
|
||||
* **important**: data must be set using `VoxelManip:set_data()` before calling this
|
||||
* `get_node_at(pos)`: Returns a `MapNode` table of the node currently loaded in
|
||||
the `VoxelManip` at that position
|
||||
* `set_node_at(pos, node)`: Sets a specific `MapNode` in the `VoxelManip` at
|
||||
that position
|
||||
* `get_data(buffer)`: Gets the data read into the `VoxelManip` object
|
||||
* `set_node_at(pos, node)`: Sets a specific `MapNode` in the `VoxelManip` at that position
|
||||
* `get_data([buffer])`: Retrieves the node content data loaded into the `VoxelManip` object
|
||||
* returns raw node data in the form of an array of node content IDs
|
||||
* if the param `buffer` is present, this table will be used to store the result instead
|
||||
* `set_data(data)`: Sets the data contents of the `VoxelManip` object
|
||||
|
Loading…
Reference in New Issue
Block a user