Allow cross-category aliases, change API
[minetest_doc.git] / API.md
blob59b88250b9d7f8e9e85ab6da87c82619ce5655f2
1 # API documentation for the Documentation System
2 ## Core concepts
3 As a modder, you are free to write basically about everything and are also
4 relatively free in the presentation of information. There are no
5 restrictions on content whatsoever.
7 ### Categories and entries
8 In the Documentation System, everything is built on categories and entries.
9 An entry is a single piece of documentation and is the basis of all actual
10 documentation. Categories group multiple entries of the same topic together.
12 Categories also define a template function which is used to determine how the
13 final result in the tab “Entry list” looks like. Entries themselves have
14 a data field attached to them, this is a table containing arbitrary metadata
15 which is used to construct the final formspec in the Entry tab. It may also
16 be used for sorting entries in the entry list.
18 ## Advanced concepts
19 ### Viewed and hidden entries
20 The mod keeps track of which entries have been viewed on a per-player basis.
21 Any entry which has been accessed by a player is immediately marked as
22 “viewed”.
24 Entries can also be hidden. Hidden entries are not visible or otherwise
25 accessible to players until they become revealed by function calls.
27 Marking an entry as viewed or revealed is not reversible with this API.
28 The viewed and hidden states are stored in the file `doc.mt` inside the
29 world directory. You can safely delete this file if you want to reset
30 the player states.
32 ### Entry aliases
33 Entry aliases are alternative identifiers for entry identifiers. With the
34 exception of the alias functions themselves, for functions demanding an
35 `entry_id` you can either supply the original `entry_id` or any alias of the
36 `entry_id`.
38 ## Possible use cases
39 This section shows some possible use cases to give you a rough idea what
40 this mod is capable of and how these use cases could be implemented.
42 ### Simple use case: Minetest basics
43 Let's say you want to write in free form short help texts about the basic
44 concepts of Minetest or your subgame. First you could define a category
45 called “Basics”, the data for each of its entry is just a free form text.
46 The template function simply creates a formspec where this free form
47 text is displayed.
49 This is one of the most simple use cases and the mod `doc_basics` does
50 exactly that.
52 ### Complex use case: Blocks
53 You could create a category called “Blocks”, and this category is supposed to
54 contain entries for every single block (i.e. node) in the game. For this use
55 case, a free form approach would be very inefficient and error-prone, as a
56 lot of data can be reused.
58 Here the template function comes in handy: The internal entry data
59 contain a lot of different things about a block, like block name, identifier,
60 custom description and most importantly, the definition table of the block.
62 Finally, the template function takes all that data and turns it into
63 sentences which are just concatenated, telling as many useful facts about
64 this block as possible.
66 ## Functions
67 This is a list of all publicly available functions.
69 ### Overview
70 The most important functions are `doc.add_category` and `doc.ad_entry`. All other functions
71 are mostly used for utility and examination purposes.
73 If not mentioned otherwise, the return value of all functions is `nil`.
75 These functions are available:
77 #### Core
78 * `doc.add_category`: Adds a new category
79 * `doc.add_entry`: Adds a new entry
81 #### Display
82 * `doc.show_entry`: Shows a particular entry to a player
83 * `doc.show_category`: Shows the entry list of a category to a player
84 * `doc.show_doc`: Opens the main help form for a player
86 #### Query
87 * `doc.get_category_definition`: Returns the definition table of a category
88 * `doc.get_entry_definition`: Returns the definition table of an entry
89 * `doc.entry_exists`: Checks whether an entry exists
90 * `doc.entry_viewed`: Checks whether an entry has been viewed/read by a player
91 * `doc.entry_revealed`: Checks whether an entry is visible and normally accessible to a player
92 * `doc.get_category_count`: Returns the total number of categories
93 * `doc.get_entry_count`: Returns the total number of entries in a category
94 * `doc.get_viewed_count`: Returns the number of entries a player has viewed in a category
95 * `doc.get_revealed_count`: Returns the number of entries a player has access to in a category
96 * `doc.get_hidden_count`: Returns the number of entries which are hidden from a player in a category
97 * `doc.get_selection`: Returns the currently viewed entry/category of a player
99 #### Modify
100 * `doc.set_category_order`: Sets the order of categories in the category list
101 * `doc.mark_entry_as_viewed`: Manually marks an entry as viewed/read by a player
102 * `doc.mark_entry_as_revealed`: Make a hidden entry visible and accessible to a player
103 * `doc.mark_all_entries_as_revealed`: Make all hidden entries visible and accessible to a player
105 #### Aliases
106 * `doc.add_entry_alias`: Add an alternative name which can be used to access an entry
108 #### Special widgets
109 This API provides functions to add unique “widgets” for functionality
110 you may find useful when creating entry templates. You find these
111 functions in `doc.widgets`.
112 Currently there is a widget for scrollable multi-line text and a
113 widget providing an image gallery.
117 ### `doc.add_category(id, def)`
118 Adds a new category. You have to define an unique identifier, a name
119 and a template function to build the entry formspec from the entry
120 data.
122 **Important**: You must call this function *before* any player joins.
124 #### Parameters
125 * `id`: Unique category identifier as a string
126 * `def`: Definition table with the following fields:
127     * `name`: Category name to be shown in the interface
128     * `description`: (optional) Short description of the category,
129        will be shown as tooltip. Recommended style (in English):
130        First letter capitalized, no punctuation at the end,
131        max. 100 characters
132     * `build_formspec`: The template function (see below). Takes entry data
133       as its first parameter (has the data type of the entry data) and the
134       name of the player who views the entry as its second parameter. It must
135       return a formspec which is inserted in the Entry tab.
136     * `sorting`: (optional) Sorting algorithm for display order of entries
137         * `"abc"`: Alphabetical (default)
138         * `"nosort"`: Entries appear in no particular order
139         * `"custom"`: Manually define the order of entries in `sorting_data`
140         * `"function"`: Sort by function defined in `sorting_data`
141     * `sorting_data`: (optional) Additional data for special sorting methods.
142         * If `sorting=="custom"`, this field must contain a table (list form) in which
143           the entry IDs are specified in the order they are supposed to appear in the
144           entry list. All entries which are missing in this table will appear in no
145           particular order below the final specified one.
146         * If `sorting=="function"`, this field is a compare function to be used as
147           the `comp` parameter of `table.sort`. The parameters given are two entries.
148         * This field is not required if `sorting` has any other value
149     * `hide_entries_by_default` (optional): If `true`, all entries
150       added to this category will start as hidden, unless explicitly specified otherwise
151       (default: `false`)
153 Note: For function-based sorting, the entries provided to the compare function
154 will have the following format:
156     {
157         eid = e,        -- unique entry identifier
158         name = n,       -- entry name
159         data = d,       -- arbitrary entry data
160     }
162 #### Using `build_formspec`
163 For `build_formspec` you can either define your own function which
164 procedurally generates the entry formspec or you use one of the
165 following predefined convenience functions:
167 * `doc.entry_builders.text`: Expects entry data to be a string.
168   It will be inserted directly into the entry. Useful for entries with
169   a free form text.
170 * `doc.entry_builders.text_and_gallery`: For entries with text and
171   an optional standard gallery (3 rows, 3:2 aspect ratio). Expects
172   entry data to be a table with these fields:
173     * `text`: The entry text
174     * `images`: The images of the gallery, the format is the same as the
175        `imagedata` parameter of `doc.widgets.gallery`. Can be `nil`, in
176        which case no gallery is shown for the entry
177 * `doc.entry_builders.formspec`: Entry data is expected to contain the
178   complete entry formspec as a string. Useful if your entries. Useful
179   if you expect your entries to differ wildly in layouts.
181 ##### Formspec restrictions
182 When building your formspec, you have to respect the size limitations.
183 The help form currently uses a size of 15×10.5 and you must make sure
184 all entry widgets are inside a boundary box. The remaining space is
185 reserved for widgets of the help form and should not be used to avoid
186 overlapping.
187 Read from the following variables to calculate the final formspec coordinates:
189 * `doc.FORMSPEC.WIDTH`: Width of help formspec
190 * `doc.FORMSPEC.HEIGHT`: Height of help formspec
191 * `doc.FORMSPEC.ENTRY_START_X`: Leftmost X point of bounding box
192 * `doc.FORMSPEC.ENTRY_START_Y`: Topmost Y point of bounding box
193 * `doc.FORMSPEC.ENTRY_END_X`: Rightmost X point of bounding box
194 * `doc.FORMSPEC.ENTRY_END_Y`: Bottom Y point of bounding box
195 * `doc.FORMSPEC.ENTRY_WIDTH`: Width of the entry widgets bounding box
196 * `doc.FORMSPEC.ENTRY_HEIGHT`: Height of the entry widgets bounding box
198 Finally, to avoid naming collisions, you must make sure that all identifiers
199 of your own formspec elements do *not* begin with “`doc_`”.
201 ##### Receiving formspec events
202 You can even use the formspec elements you have added with `build_formspec` to
203 receive formspec events, just like with any other formspec. For receiving, use
204 the standard function `minetest.register_on_player_receive_fields` to register
205 your event handling. The `formname` parameter will be `doc:entry`. Use
206 `doc.get_selection` to get the category ID and entry ID of the entry in question.
208 ### `doc.add_entry(category_id, entry_id, def)`
209 Adds a new entry into an existing category. You have to define the category
210 to which to insert the entry, the entry's identifier, a name and some
211 data which defines the entry. Note you do not directly define here how the
212 end result of an entry looks like, this is done by `build_formspec` from
213 the category definition.
215 **Important**: You must call this function *before* any player joins.
217 #### Parameters
218 * `category_id`: Identifier of the category to add the entry into
219 * `entry_id`: Unique identifier of the new entry, as a string
220 * `def`: Definition table, it has the following fields:
221     * `name`: Entry name to be shown in the interface
222     * `hidden`: (optional) If `true`, entry will not be displayed in entry list
223       initially (default: `false`); it can be revealed later
224     * `data`: Arbitrary data attached to the entry. Any data type is allowed;
225       The data in this field will be used to create the actual formspec
226       with `build_formspec` from the category definition
228 ### `doc.set_category_order(category_list)`
229 Sets the order of categories in the category list.
230 The help starts with this default order:
232     {"basics", "nodes", "tools", "craftitems", "advanced"}
234 This function can be called at any time, but it recommended to only call
235 this function once for the entire server session and to only call it
236 from subgame mods, to avoid contradictions. If this function is called a
237 second time by any mod, a warning is written into the log.
239 #### Parameters
240 * `category_list`: List of category IDs in the order they should appear
241   in the category list. All unspecified categories will be appended to
242   the end
245 ### `doc.show_doc(playername)`
246 Opens the main help formspec for the player (“Category list” tab).
248 #### Parameters
249 * `playername`: Name of the player to show the formspec to
251 ### `doc.show_category(playername, category_id)`
252 Opens the help formspec for the player at the specified category
253 (“Entry list” tab).
255 #### Parameters
256 * `playername`: Name of the player to show the formspec to
257 * `category_id`: Category identifier of the selected category
259 ### `doc.show_entry(playername, category_id, entry_id, ignore_hidden)`
260 Opens the help formspec for the player showing the specified entry
261 of a category (“Entry” tab). If the entry is hidden, an error message
262 is displayed unless `ignore_hidden==true`.
264 #### Parameters
265 * `playername`: Name of the player to show the formspec to
266 * `category_id`: Category identifier of the selected category
267 * `entry_id`: Entry identifier of the entry to show
268 * `ignore_hidden`: (optional) If `true`, shows entry even if it is still hidden
269   to the player; this will automatically reveal the entry to this player for the
270   rest of the game
272 ### `doc.get_category_definition(category_id)`
273 Returns the definition of the specified category.
275 #### Parameters
276 * `category_id`: Category identifier of the category to the the definition
277   for
279 #### Return value
280 The category's definition table as specified in the `def` argument of
281 `doc.add_category`. The table fields are the same.
283 ### `doc.get_entry_definition(category_id, entry_id)`
284 Returns the definition of the specified entry.
286 #### Parameters
287 * `category_id`: Category identifier of entry's category
288 * `entry_id`: Entry identifier of the entry to get the definition for
290 #### Return value
291 The entry's definition table as specified in the `def` argument of
292 `doc.add_entry`. The table fields are the same.
294 ### `doc.entry_exists(category_id, entry_id)`
295 Checks whether the specified entry exists and returns `true` or `false`.
296 Entry aliases are taken into account.
298 #### Parameters
299 * `category_id`: Category identifier of the category to check
300 * `entry_id`: Entry identifier of the entry to check for its existence
302 #### Return value
303 Returns `true` if and only if:
305 * The specified category exists
306 * It contains the specified entry
308 Otherwise, returns `false`.
310 ### `doc.entry_viewed(playername, category_id, entry_id)`
311 Tells whether the specified entry is marked as “viewed” (or read) by
312 the player.
314 #### Parameters
315 * `playername`: Name of the player to check
316 * `category_id`: Category identifier of the category to check
317 * `entry_id`: Entry identifier of the entry to check
319 #### Return value
320 `true`, if entry is viewed, `false` otherwise.
322 ### `doc.entry_revealed(playername, category_id, entry_id)`
323 Tells whether the specified entry is marked as “revealed” to the player
324 and thus visible and accessible to the player.
326 #### Parameters
327 * `playername`: Name of the player to check
328 * `category_id`: Category identifier of the category to check
329 * `entry_id`: Entry identifier of the entry to check
331 #### Return value
332 `true`, if entry is revealed, `false` otherwise.
334 ### `doc.mark_entry_as_viewed(playername, category_id, entry_id)`
335 Marks a particular entry as “viewed” (or read) by a player. This will
336 also automatically reveal the entry to the player for the rest of
337 the game.
339 #### Parameters
340 * `playername`: Name of the player for whom to mark an entry as “viewed”
341 * `category_id`: Category identifier of the category of the entry to mark
342 * `entry_id`: Entry identifier of the entry to mark
344 ### `doc.mark_entry_as_revealed(playername, category_id, entry_id)`
345 Marks a particular entry as “revealed” to a player. If the entry is
346 declared as hidden, it will become visible in the list of entries for
347 this player and will always be accessible with `doc.show_entry`. This
348 change remains for the rest of the game.
350 For entries which are not normally hidden, this function has no direct
351 effect.
353 #### Parameters
354 * `playername`: Name of the player for whom to reveal the entry
355 * `category_id`: Category identifier of the category of the entry to reveal
356 * `entry_id`: Entry identifier of the entry to reveal
358 ### `doc.mark_all_entries_as_revealed(playername)`
359 Marks all entries as “revealed” to a player. This change remains for the
360 rest of the game.
362 #### Parameters
363 * `playername`: Name of the player for whom to reveal the entries
365 ### `doc.add_entry_alias(category_id_orig, entry_id_orig, category_id_alias, entry_id_orig)`
366 Adds a single alias for an entry. If an entry has an alias, supplying the
367 alias to a function which demand `category_id` and `entry_id` will work as expected.
368 When using this function, you must make sure the category already exists.
370 This function could be useful for legacy support after changing an entry ID or
371 moving an entry to a different category.
373 #### Parameters
374 * `category_id_orig`: Category identifier of the category of the entry in question
375 * `entry_id_orig`: The original (!) entry identifier of the entry to create an alias
376   for
377 * `category_id_alias`: The category ID of the alias
378 * `entry_id_alias`: The entry ID of the alias
380 #### Example
382     doc.add_entry_alias("nodes", "test", "craftitems", "test2")
384 When calling a function with category ID “craftitems” and entry ID “test2”, it will
385 act as if you supplied “nodes” as category ID and “test” as entry ID.
387 ### `doc.get_category_count()`
388 Returns the number of registered categories.
390 #### Return value
391 Number of registered categories.
393 ### `doc.get_entry_count(category_id)`
394 Returns the number of entries in a category.
396 #### Parameters
397 * `category_id`: Category identifier of the category in which to count entries
399 #### Return value
400 Number of entries in the specified category.
402 ### `doc.get_viewed_count(playername, category_id)`
403 Returns how many entries have been viewed by a player.
405 #### Parameters
406 * `playername`: Name of the player to count the viewed entries for
407 * `category_id`: Category identifier of the category in which to count the
408   viewed entries
410 #### Return value
411 Amount of entries the player has viewed in the specified category. If the
412 player does not exist, this function returns `nil`.
414 ### `doc.get_revealed_count(playername, category_id)`
415 Returns how many entries the player has access to (non-hidden entries)
416 in this category.
418 #### Parameters
419 * `playername`: Name of the player to count the revealed entries for
420 * `category_id`: Category identifier of the category in which to count the
421   revealed entries
423 #### Return value
424 Amount of entries the player has access to in the specified category. If the
425 player does not exist, this function returns `nil`.
427 ### `doc.get_hidden_count(playername, category_id)`
428 Returns how many entries are hidden from the player in this category.
430 #### Parameters
431 * `playername`: Name of the player to count the hidden entries for
432 * `category_id`: Category identifier of the category in which to count the
433   hidden entries
435 #### Return value
436 Amount of entries hidden from the player. If the player does not exist,
437 this function returns `nil`.
439 ### `doc.get_selection(playername)`
440 Returns the currently or last viewed entry and/or category of a player.
442 #### Parameter
443 * `playername`: Name of the player to query
445 #### Return value
446 It returns up to 2 values. The first one is the category ID, the second one
447 is the entry ID of the entry/category which the player is currently viewing
448 or is the last entry the player viewed in this session. If the player only
449 viewed a category so far, the second value is `nil`. If the player has not
450 viewed a category as well, both returned values are `nil`.
453 ### `doc.widgets.text(data, x, y, width, height)`
454 This is a convenience function for creating a special formspec widget. It creates
455 a widget in which you can insert scrollable multi-line text.
457 As of Minetest 0.4.14, this function is only provided because Minetest lacks
458 native support for such a widget. When Minetest supports such a widget natively,
459 this function may become just a simple wrapper.
461 #### Parameters
462 * `data`: Text to be written inside the widget
463 * `x`: Formspec X coordinate (optional)
464 * `y`: Formspec Y coordinate (optional)
465 * `width`: Width of the widget in formspec units (optional)
466 * `height`: Height of the widget in formspec units (optional)
468 The default values for the optional parameters result in a widget which fills
469 nearly the entire entry page.
471 #### Return value
472 Two values are returned, in this order:
474 * string: Contains a complete formspec definition building the widget
475 * string: Formspec element ID of the created widget
477 #### Note
478 If you use this function to build a formspec string, do not use identifiers
479 beginning with `doc_widget_text` to avoid naming collisions, as this function
480 makes use of such identifiers internally.
483 ### `doc.widgets.gallery(imagedata, playername, x, y, aspect_ratio, width, rows, align_left, align_top)`
484 This function creates an image gallery which allows you to display an
485 arbitrary amount of images aligned horizontally. It is possible to add more
486 images than the space of an entry would normally held, this is done by adding
487 “scroll” buttons to the left and right which allows the user to see more images
488 of the gallery.
490 This function is useful for adding multiple illustration to your entry without
491 worrying about space too much. Adding illustrations can help you to create
492 entry templates which aren't just lengthy walls of text. ;-)
494 You can define the position, image aspect ratio, total gallery width and the
495 number of images displayed at once. You can *not* directly define the image
496 size, nor the resulting height of the overall gallery, those values will
497 be derived from the parameters.
499 You can only really use this function efficiently inside a *custom*
500 `build_formspec` function definition. This is because you need to pass a
501 `playername`. You can currently also only add up to one gallery per entry;
502 adding more galleries is not supported and will lead to bugs.
504 ### Parameters
505 * `imagedata`: List of images to be displayed in the specified order. All images must
506    have the same aspect ratio. It's a table of tables with this format:
507     * `imagetype`: Type of image to be used (optional):
508         * `"image"`: Texture file (default)
509         * `"item"`: Item image, specified as itemstring
510     * `image`: What to display. Depending on `imagetype`, a texture file or itemstring
511 * `playername`: Name of the player who is viewing the entry in question
512 * `x`: Formspec X coordinate of the top left corner (optional)
513 * `y`: Formspec Y coordinate of the top left corner (optional)
514 * `aspect_ratio`: Aspect ratio of all the images (width/height)
515 * `width`: Total gallery width in formspec units (optional)
516 * `rows`: Number of images which can be seen at once (optional)
517 * `align_left`: If `false`, gallery is aligned to the left instead of the right (optional)
518 * `align_right`: If `false`, gallery is aligned to the bottom instead of the top (optional)
520 The default values for the optional parameters result in a gallery with
521 3 rows which is placed at the top left corner and spans the width of the
522 entry and assumes an aspect ratio of two thirds.
524 If the number of images is greater than `rows`, “scroll” buttons will appear
525 at the left and right side of the images.
527 #### Return values
528 Two values are returned, in this order:
530 * string: Contains a complete formspec definition building the gallery
531 * number: The height the gallery occupies in the formspec
533 ## Extending this mod (naming conventions)
534 If you want to extend this mod with your own functionality, it is recommended
535 that you put all API functions into `doc.sub.<name>`.
536 As a naming convention, if you mod *primarily* depends on `doc`, it is recommended
537 to use a short mod name which starts with “`doc_`”, like `doc_items`,
538 `doc_minetest_game`, or `doc_identifier`.
540 One mod which uses this convention is `doc_items` which uses the `doc.sub.items`
541 table.