From 452e989870c6c38c7398d4867067a62931649929 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Sat, 26 Aug 2023 10:44:26 +0200 Subject: [PATCH] built on 26/08/2023 10:44:26 --- README.md | 22 +- datastorage/README.md | 22 - datastorage/init.lua | 98 -- datastorage/mod.conf | 2 - doc/API.md | 539 -------- doc/README.md | 52 - doc/init.lua | 1220 ----------------- doc/locale/doc.de.tr | 51 - doc/locale/doc.pt.tr | 43 - doc/locale/doc.pt_BR.tr | 43 - doc/locale/template.txt | 51 - doc/mod.conf | 3 - doc/screenshot.png | Bin 12315 -> 0 bytes doc/sounds/doc_reveal.ogg | Bin 8873 -> 0 bytes doc/textures/doc_awards_icon_generic.png | Bin 639 -> 0 bytes doc/textures/doc_button_icon_hires.png | Bin 2336 -> 0 bytes doc/textures/doc_button_icon_lores.png | Bin 722 -> 0 bytes .../inventory_plus_doc_inventory_plus.png | Bin 722 -> 0 bytes 18 files changed, 20 insertions(+), 2126 deletions(-) delete mode 100644 datastorage/README.md delete mode 100644 datastorage/init.lua delete mode 100644 datastorage/mod.conf delete mode 100644 doc/API.md delete mode 100644 doc/README.md delete mode 100644 doc/init.lua delete mode 100644 doc/locale/doc.de.tr delete mode 100644 doc/locale/doc.pt.tr delete mode 100644 doc/locale/doc.pt_BR.tr delete mode 100644 doc/locale/template.txt delete mode 100644 doc/mod.conf delete mode 100644 doc/screenshot.png delete mode 100644 doc/sounds/doc_reveal.ogg delete mode 100644 doc/textures/doc_awards_icon_generic.png delete mode 100644 doc/textures/doc_button_icon_hires.png delete mode 100644 doc/textures/doc_button_icon_lores.png delete mode 100644 doc/textures/inventory_plus_doc_inventory_plus.png diff --git a/README.md b/README.md index c4bd016..b2780fb 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,12 @@ This modpack contains: - towercrane: Simplifies the building of large techage plants - basic_materials: Needed items for many recipes - stamina: The "hunger" mod from "minetest-mods" -- doc: Ingame documentation mod, used for minecart and signs_bot - unified_inventory: Player's inventory with crafting guide, bags, and more. - tubelib2: Necessary library - networks: Necessary library - safer_lua: Necessary library - lcdlib: Necessary library -- datastorage: Necessary library +- doclib: Necessary library ### Techage Manual @@ -47,6 +46,25 @@ ta4_jetpack requires the modpack 3d_armor. 3d_armor is itself a modpack and can' ### History +#### 2023-08-25 + +Updated Mods: + +- techage v1.17: + - see readme.md +- autobahn: + - Make motor sound mono (Niklp09) +- lcdlib v1.02: + - see readme.md +- signs_bot v1.13: + - see readme.md +- minecart v2.05: + - see readme.md +- mod 'doc' removed +- mod 'doclib' v1.00 added + **The mod doclib is a new hard depenency !** +- mod 'datastorage' removed + #### 2023-05-09 Updated Mods: diff --git a/datastorage/README.md b/datastorage/README.md deleted file mode 100644 index b15b07a..0000000 --- a/datastorage/README.md +++ /dev/null @@ -1,22 +0,0 @@ -datastorage -=========== - -Helper mod to manage players data. -All the mods can acces a single file (container) and easily have the data saved/loaded for them. - -Usage ------ - - local data = datastorage.get(id, ...) - -Returns a reference to a data container. The id is normally a player name. -Following arguments are keys to recurse into, normally only one, a string -describing the type of data, is used. If the container doesn't exist it will -be created, otherwise it will contain all previously stored data. The table -can store any data. Player's containers will be saved to disk when the player -leaves, and all references to the player's data should be dropped. All of the -containers will be saved on server shutdown. To forcibly save a container's -data use: - - datastorage.save(id) - diff --git a/datastorage/init.lua b/datastorage/init.lua deleted file mode 100644 index 30677fc..0000000 --- a/datastorage/init.lua +++ /dev/null @@ -1,98 +0,0 @@ -datastorage = {data = {}} - -local DIR_DELIM = DIR_DELIM or "/" -local data_path = minetest.get_worldpath()..DIR_DELIM.."datastorage"..DIR_DELIM - -function datastorage.save(id) - local data = datastorage.data[id] - -- Check if the container is empty - if not data or not next(data) then return end - for _, sub_data in pairs(data) do - if not next(sub_data) then return end - end - - local file = io.open(data_path..id, "w") - if not file then - -- Most likely the data directory doesn't exist, create it - -- and try again. - if minetest.mkdir then - minetest.mkdir(data_path) - else - -- Using os.execute like this is not very platform - -- independent or safe, but most platforms name their - -- directory creation utility mkdir, the data path is - -- unlikely to contain special characters, and the - -- data path is only mutable by the admin. - os.execute('mkdir "'..data_path..'"') - end - file = io.open(data_path..id, "w") - if not file then return end - end - - local datastr = minetest.serialize(data) - if not datastr then return end - - file:write(datastr) - file:close() - return true -end - -function datastorage.load(id) - local file = io.open(data_path..id, "r") - if not file then return end - - local data = minetest.deserialize(file:read("*all")) - datastorage.data[id] = data - - file:close() - return data -end - --- Compatability -function datastorage.get_container(player, id) - return datastorage.get(player:get_player_name(), id) -end - --- Retrieves a value from the data storage -function datastorage.get(id, ...) - local last = datastorage.data[id] - if last == nil then last = datastorage.load(id) end - if last == nil then - last = {} - datastorage.data[id] = last - end - local cur = last - for _, sub_id in ipairs({...}) do - last = cur - cur = cur[sub_id] - if cur == nil then - cur = {} - last[sub_id] = cur - end - end - return cur -end - --- Saves a container and reomves it from memory -function datastorage.finish(id) - datastorage.save(id) - datastorage.data[id] = nil -end - --- Compatability -function datastorage.save_container(player) - return datastorage.save(player:get_player_name()) -end - -minetest.register_on_leaveplayer(function(player) - local player_name = player:get_player_name() - datastorage.save(player_name) - datastorage.data[player_name] = nil -end) - -minetest.register_on_shutdown(function() - for id in pairs(datastorage.data) do - datastorage.save(id) - end -end) - diff --git a/datastorage/mod.conf b/datastorage/mod.conf deleted file mode 100644 index 39a27d2..0000000 --- a/datastorage/mod.conf +++ /dev/null @@ -1,2 +0,0 @@ -name=datastorage -description=Helper mod to manage players data. diff --git a/doc/API.md b/doc/API.md deleted file mode 100644 index 49afeb3..0000000 --- a/doc/API.md +++ /dev/null @@ -1,539 +0,0 @@ -# API documentation for the Documentation System -## Core concepts -As a modder, you are free to write basically about everything and are also -relatively free in the presentation of information. There are no -restrictions on content whatsoever. - -### Categories and entries -In the Documentation System, everything is built on categories and entries. -An entry is a single piece of documentation and is the basis of all actual -documentation. Categories group multiple entries of the same topic together. - -Categories also define a template function which is used to determine how the -final result in the tab “Entry list” looks like. Entries themselves have -a data field attached to them, this is a table containing arbitrary metadata -which is used to construct the final formspec in the Entry tab. It may also -be used for sorting entries in the entry list. - -## Advanced concepts -### Viewed and hidden entries -The mod keeps track of which entries have been viewed on a per-player basis. -Any entry which has been accessed by a player is immediately marked as -“viewed”. - -Entries can also be hidden. Hidden entries are not visible or otherwise -accessible to players until they become revealed by function calls. - -Marking an entry as viewed or revealed is not reversible with this API. -The viewed and hidden states are stored in the file `doc.mt` inside the -world directory. You can safely delete this file if you want to reset -the player states. - -### Entry aliases -Entry aliases are alternative identifiers for entry identifiers. With the -exception of the alias functions themselves, for functions demanding an -`entry_id` you can either supply the original `entry_id` or any alias of the -`entry_id`. - -## Possible use cases -This section shows some possible use cases to give you a rough idea what -this mod is capable of and how these use cases could be implemented. - -### Simple use case: Minetest basics -Let's say you want to write in free form short help texts about the basic -concepts of Minetest or your game. First you could define a category -called “Basics”, the data for each of its entry is just a free form text. -The template function simply creates a formspec where this free form -text is displayed. - -This is one of the most simple use cases and the mod `doc_basics` does -exactly that. - -### Complex use case: Blocks -You could create a category called “Blocks”, and this category is supposed to -contain entries for every single block (i.e. node) in the game. For this use -case, a free form approach would be very inefficient and error-prone, as a -lot of data can be reused. - -Here the template function comes in handy: The internal entry data -contain a lot of different things about a block, like block name, identifier, -custom description and most importantly, the definition table of the block. - -Finally, the template function takes all that data and turns it into -sentences which are just concatenated, telling as many useful facts about -this block as possible. - -## Functions -This is a list of all publicly available functions. - -### Overview -The most important functions are `doc.add_category` and `doc.ad_entry`. All other functions -are mostly used for utility and examination purposes. - -If not mentioned otherwise, the return value of all functions is `nil`. - -These functions are available: - -#### Core -* `doc.add_category`: Adds a new category -* `doc.add_entry`: Adds a new entry - -#### Display -* `doc.show_entry`: Shows a particular entry to a player -* `doc.show_category`: Shows the entry list of a category to a player -* `doc.show_doc`: Opens the main help form for a player - -#### Query -* `doc.get_category_definition`: Returns the definition table of a category -* `doc.get_entry_definition`: Returns the definition table of an entry -* `doc.entry_exists`: Checks whether an entry exists -* `doc.entry_viewed`: Checks whether an entry has been viewed/read by a player -* `doc.entry_revealed`: Checks whether an entry is visible and normally accessible to a player -* `doc.get_category_count`: Returns the total number of categories -* `doc.get_entry_count`: Returns the total number of entries in a category -* `doc.get_viewed_count`: Returns the number of entries a player has viewed in a category -* `doc.get_revealed_count`: Returns the number of entries a player has access to in a category -* `doc.get_hidden_count`: Returns the number of entries which are hidden from a player in a category -* `doc.get_selection`: Returns the currently viewed entry/category of a player - -#### Modify -* `doc.set_category_order`: Sets the order of categories in the category list -* `doc.mark_entry_as_viewed`: Manually marks an entry as viewed/read by a player -* `doc.mark_entry_as_revealed`: Make a hidden entry visible and accessible to a player -* `doc.mark_all_entries_as_revealed`: Make all hidden entries visible and accessible to a player - -#### Aliases -* `doc.add_entry_alias`: Add an alternative name which can be used to access an entry - -#### Special widgets -This API provides functions to add unique “widgets” for functionality -you may find useful when creating entry templates. You find these -functions in `doc.widgets`. -Currently there is a widget for scrollable multi-line text and a -widget providing an image gallery. - - - -### `doc.add_category(id, def)` -Adds a new category. You have to define an unique identifier, a name -and a template function to build the entry formspec from the entry -data. - -**Important**: You must call this function *before* any player joins. - -#### Parameters -* `id`: Unique category identifier as a string -* `def`: Definition table with the following fields: - * `name`: Category name to be shown in the interface - * `description`: (optional) Short description of the category, - will be shown as tooltip. Recommended style (in English): - First letter capitalized, no punctuation at the end, - max. 100 characters - * `build_formspec`: The template function (see below). Takes entry data - as its first parameter (has the data type of the entry data) and the - name of the player who views the entry as its second parameter. It must - return a formspec which is inserted in the Entry tab. - * `sorting`: (optional) Sorting algorithm for display order of entries - * `"abc"`: Alphabetical (default) - * `"nosort"`: Entries appear in no particular order - * `"custom"`: Manually define the order of entries in `sorting_data` - * `"function"`: Sort by function defined in `sorting_data` - * `sorting_data`: (optional) Additional data for special sorting methods. - * If `sorting=="custom"`, this field must contain a table (list form) in which - the entry IDs are specified in the order they are supposed to appear in the - entry list. All entries which are missing in this table will appear in no - particular order below the final specified one. - * If `sorting=="function"`, this field is a compare function to be used as - the `comp` parameter of `table.sort`. The parameters given are two entries. - * This field is not required if `sorting` has any other value - * `hide_entries_by_default` (optional): If `true`, all entries - added to this category will start as hidden, unless explicitly specified otherwise - (default: `false`) - -Note: For function-based sorting, the entries provided to the compare function -will have the following format: - - { - eid = e, -- unique entry identifier - name = n, -- entry name - data = d, -- arbitrary entry data - } - -#### Using `build_formspec` -For `build_formspec` you can either define your own function which -procedurally generates the entry formspec or you use one of the -following predefined convenience functions: - -* `doc.entry_builders.text`: Expects entry data to be a string. - It will be inserted directly into the entry. Useful for entries with - a free form text. -* `doc.entry_builders.text_and_gallery`: For entries with text and - an optional standard gallery (3 rows, 3:2 aspect ratio). Expects - entry data to be a table with these fields: - * `text`: The entry text - * `images`: The images of the gallery, the format is the same as the - `imagedata` parameter of `doc.widgets.gallery`. Can be `nil`, in - which case no gallery is shown for the entry -* `doc.entry_builders.formspec`: Entry data is expected to contain the - complete entry formspec as a string. Useful if your entries. Useful - if you expect your entries to differ wildly in layouts. - -##### Formspec restrictions -When building your formspec, you have to respect the size limitations. -The help form currently uses a size of 15×10.5 and you must make sure -all entry widgets are inside a boundary box. The remaining space is -reserved for widgets of the help form and should not be used to avoid -overlapping. -Read from the following variables to calculate the final formspec coordinates: - -* `doc.FORMSPEC.WIDTH`: Width of help formspec -* `doc.FORMSPEC.HEIGHT`: Height of help formspec -* `doc.FORMSPEC.ENTRY_START_X`: Leftmost X point of bounding box -* `doc.FORMSPEC.ENTRY_START_Y`: Topmost Y point of bounding box -* `doc.FORMSPEC.ENTRY_END_X`: Rightmost X point of bounding box -* `doc.FORMSPEC.ENTRY_END_Y`: Bottom Y point of bounding box -* `doc.FORMSPEC.ENTRY_WIDTH`: Width of the entry widgets bounding box -* `doc.FORMSPEC.ENTRY_HEIGHT`: Height of the entry widgets bounding box - -Finally, to avoid naming collisions, you must make sure that all identifiers -of your own formspec elements do *not* begin with “`doc_`”. - -##### Receiving formspec events -You can even use the formspec elements you have added with `build_formspec` to -receive formspec events, just like with any other formspec. For receiving, use -the standard function `minetest.register_on_player_receive_fields` to register -your event handling. The `formname` parameter will be `doc:entry`. Use -`doc.get_selection` to get the category ID and entry ID of the entry in question. - -### `doc.add_entry(category_id, entry_id, def)` -Adds a new entry into an existing category. You have to define the category -to which to insert the entry, the entry's identifier, a name and some -data which defines the entry. Note you do not directly define here how the -end result of an entry looks like, this is done by `build_formspec` from -the category definition. - -**Important**: You must call this function *before* any player joins. - -#### Parameters -* `category_id`: Identifier of the category to add the entry into -* `entry_id`: Unique identifier of the new entry, as a string -* `def`: Definition table, it has the following fields: - * `name`: Entry name to be shown in the interface - * `hidden`: (optional) If `true`, entry will not be displayed in entry list - initially (default: `false`); it can be revealed later - * `data`: Arbitrary data attached to the entry. Any data type is allowed; - The data in this field will be used to create the actual formspec - with `build_formspec` from the category definition - -### `doc.set_category_order(category_list)` -Sets the order of categories in the category list. -The help starts with this default order: - - {"basics", "nodes", "tools", "craftitems", "advanced"} - -This function can be called at any time, but it recommended to only call -this function once for the entire server session and to only call it -from game mods, to avoid contradictions. If this function is called a -second time by any mod, a warning is written into the log. - -#### Parameters -* `category_list`: List of category IDs in the order they should appear - in the category list. All unspecified categories will be appended to - the end - - -### `doc.show_doc(playername)` -Opens the main help formspec for the player (“Category list” tab). - -#### Parameters -* `playername`: Name of the player to show the formspec to - -### `doc.show_category(playername, category_id)` -Opens the help formspec for the player at the specified category -(“Entry list” tab). - -#### Parameters -* `playername`: Name of the player to show the formspec to -* `category_id`: Category identifier of the selected category - -### `doc.show_entry(playername, category_id, entry_id, ignore_hidden)` -Opens the help formspec for the player showing the specified entry -of a category (“Entry” tab). If the entry is hidden, an error message -is displayed unless `ignore_hidden==true`. - -#### Parameters -* `playername`: Name of the player to show the formspec to -* `category_id`: Category identifier of the selected category -* `entry_id`: Entry identifier of the entry to show -* `ignore_hidden`: (optional) If `true`, shows entry even if it is still hidden - to the player; this will automatically reveal the entry to this player for the - rest of the game - -### `doc.get_category_definition(category_id)` -Returns the definition of the specified category. - -#### Parameters -* `category_id`: Category identifier of the category to the the definition - for - -#### Return value -The category's definition table as specified in the `def` argument of -`doc.add_category`. The table fields are the same. - -### `doc.get_entry_definition(category_id, entry_id)` -Returns the definition of the specified entry. - -#### Parameters -* `category_id`: Category identifier of entry's category -* `entry_id`: Entry identifier of the entry to get the definition for - -#### Return value -The entry's definition table as specified in the `def` argument of -`doc.add_entry`. The table fields are the same. - -### `doc.entry_exists(category_id, entry_id)` -Checks whether the specified entry exists and returns `true` or `false`. -Entry aliases are taken into account. - -#### Parameters -* `category_id`: Category identifier of the category to check -* `entry_id`: Entry identifier of the entry to check for its existence - -#### Return value -Returns `true` if and only if: - -* The specified category exists -* It contains the specified entry - -Otherwise, returns `false`. - -### `doc.entry_viewed(playername, category_id, entry_id)` -Tells whether the specified entry is marked as “viewed” (or read) by -the player. - -#### Parameters -* `playername`: Name of the player to check -* `category_id`: Category identifier of the category to check -* `entry_id`: Entry identifier of the entry to check - -#### Return value -`true`, if entry is viewed, `false` otherwise. - -### `doc.entry_revealed(playername, category_id, entry_id)` -Tells whether the specified entry is marked as “revealed” to the player -and thus visible and accessible to the player. - -#### Parameters -* `playername`: Name of the player to check -* `category_id`: Category identifier of the category to check -* `entry_id`: Entry identifier of the entry to check - -#### Return value -`true`, if entry is revealed, `false` otherwise. - -### `doc.mark_entry_as_viewed(playername, category_id, entry_id)` -Marks a particular entry as “viewed” (or read) by a player. This will -also automatically reveal the entry to the player for the rest of -the game. - -#### Parameters -* `playername`: Name of the player for whom to mark an entry as “viewed” -* `category_id`: Category identifier of the category of the entry to mark -* `entry_id`: Entry identifier of the entry to mark - -### `doc.mark_entry_as_revealed(playername, category_id, entry_id)` -Marks a particular entry as “revealed” to a player. If the entry is -declared as hidden, it will become visible in the list of entries for -this player and will always be accessible with `doc.show_entry`. This -change remains for the rest of the game. - -For entries which are not normally hidden, this function has no direct -effect. - -#### Parameters -* `playername`: Name of the player for whom to reveal the entry -* `category_id`: Category identifier of the category of the entry to reveal -* `entry_id`: Entry identifier of the entry to reveal - -### `doc.mark_all_entries_as_revealed(playername)` -Marks all entries as “revealed” to a player. This change remains for the -rest of the game. - -#### Parameters -* `playername`: Name of the player for whom to reveal the entries - -### `doc.add_entry_alias(category_id_orig, entry_id_orig, category_id_alias, entry_id_alias)` -Adds a single alias for an entry. If an entry has an alias, supplying the -alias to a function which demand `category_id` and `entry_id` will work as expected. -When using this function, you must make sure the category already exists. - -This function could be useful for legacy support after changing an entry ID or -moving an entry to a different category. - -#### Parameters -* `category_id_orig`: Category identifier of the category of the entry in question -* `entry_id_orig`: The original (!) entry identifier of the entry to create an alias - for -* `category_id_alias`: The category ID of the alias -* `entry_id_alias`: The entry ID of the alias - -#### Example - - doc.add_entry_alias("nodes", "test", "craftitems", "test2") - -When calling a function with category ID “craftitems” and entry ID “test2”, it will -act as if you supplied “nodes” as category ID and “test” as entry ID. - -### `doc.get_category_count()` -Returns the number of registered categories. - -#### Return value -Number of registered categories. - -### `doc.get_entry_count(category_id)` -Returns the number of entries in a category. - -#### Parameters -* `category_id`: Category identifier of the category in which to count entries - -#### Return value -Number of entries in the specified category. - -### `doc.get_viewed_count(playername, category_id)` -Returns how many entries have been viewed by a player. - -#### Parameters -* `playername`: Name of the player to count the viewed entries for -* `category_id`: Category identifier of the category in which to count the - viewed entries - -#### Return value -Amount of entries the player has viewed in the specified category. If the -player does not exist, this function returns `nil`. - -### `doc.get_revealed_count(playername, category_id)` -Returns how many entries the player has access to (non-hidden entries) -in this category. - -#### Parameters -* `playername`: Name of the player to count the revealed entries for -* `category_id`: Category identifier of the category in which to count the - revealed entries - -#### Return value -Amount of entries the player has access to in the specified category. If the -player does not exist, this function returns `nil`. - -### `doc.get_hidden_count(playername, category_id)` -Returns how many entries are hidden from the player in this category. - -#### Parameters -* `playername`: Name of the player to count the hidden entries for -* `category_id`: Category identifier of the category in which to count the - hidden entries - -#### Return value -Amount of entries hidden from the player. If the player does not exist, -this function returns `nil`. - -### `doc.get_selection(playername)` -Returns the currently or last viewed entry and/or category of a player. - -#### Parameter -* `playername`: Name of the player to query - -#### Return value -It returns up to 2 values. The first one is the category ID, the second one -is the entry ID of the entry/category which the player is currently viewing -or is the last entry the player viewed in this session. If the player only -viewed a category so far, the second value is `nil`. If the player has not -viewed a category as well, both returned values are `nil`. - - -### `doc.widgets.text(data, x, y, width, height)` -This is a convenience function for creating a special formspec widget. It creates -a widget in which you can insert scrollable multi-line text. - -#### Parameters -* `data`: Text to be written inside the widget -* `x`: Formspec X coordinate (optional) -* `y`: Formspec Y coordinate (optional) -* `width`: Width of the widget in formspec units (optional) -* `height`: Height of the widget in formspec units (optional) - -The default values for the optional parameters result in a widget which fills -nearly the entire entry page. - -#### Return value -Two values are returned, in this order: - -* string: Contains a complete formspec definition building the widget -* string: Formspec element ID of the created widget - -#### Note -If you use this function to build a formspec string, do not use identifiers -beginning with `doc_widget_text` to avoid naming collisions, as this function -makes use of such identifiers internally. - - -### `doc.widgets.gallery(imagedata, playername, x, y, aspect_ratio, width, rows, align_left, align_top)` -This function creates an image gallery which allows you to display an -arbitrary amount of images aligned horizontally. It is possible to add more -images than the space of an entry would normally held, this is done by adding -“scroll” buttons to the left and right which allows the user to see more images -of the gallery. - -This function is useful for adding multiple illustration to your entry without -worrying about space too much. Adding illustrations can help you to create -entry templates which aren't just lengthy walls of text. ;-) - -You can define the position, image aspect ratio, total gallery width and the -number of images displayed at once. You can *not* directly define the image -size, nor the resulting height of the overall gallery, those values will -be derived from the parameters. - -You can only really use this function efficiently inside a *custom* -`build_formspec` function definition. This is because you need to pass a -`playername`. You can currently also only add up to one gallery per entry; -adding more galleries is not supported and will lead to bugs. - -### Parameters -* `imagedata`: List of images to be displayed in the specified order. All images must - have the same aspect ratio. It's a table of tables with this format: - * `imagetype`: Type of image to be used (optional): - * `"image"`: Texture file (default) - * `"item"`: Item image, specified as itemstring - * `image`: What to display. Depending on `imagetype`, a texture file or itemstring -* `playername`: Name of the player who is viewing the entry in question -* `x`: Formspec X coordinate of the top left corner (optional) -* `y`: Formspec Y coordinate of the top left corner (optional) -* `aspect_ratio`: Aspect ratio of all the images (width/height) -* `width`: Total gallery width in formspec units (optional) -* `rows`: Number of images which can be seen at once (optional) -* `align_left`: If `false`, gallery is aligned to the left instead of the right (optional) -* `align_right`: If `false`, gallery is aligned to the bottom instead of the top (optional) - -The default values for the optional parameters result in a gallery with -3 rows which is placed at the top left corner and spans the width of the -entry and assumes an aspect ratio of two thirds. - -If the number of images is greater than `rows`, “scroll” buttons will appear -at the left and right side of the images. - -#### Return values -Two values are returned, in this order: - -* string: Contains a complete formspec definition building the gallery -* number: The height the gallery occupies in the formspec - -## Extending this mod (naming conventions) -If you want to extend this mod with your own functionality, it is recommended -that you put all API functions into `doc.sub.`. -As a naming convention, if you mod *primarily* depends on `doc`, it is recommended -to use a short mod name which starts with “`doc_`”, like `doc_items`, -`doc_minetest_game`, or `doc_identifier`. - -One mod which uses this convention is `doc_items` which uses the `doc.sub.items` -table. - - diff --git a/doc/README.md b/doc/README.md deleted file mode 100644 index 802701c..0000000 --- a/doc/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# Documentation System [`doc`] -This mod provides a simple and highly extensible form in which the user -can access help pages about various things and the modder can add those pages. -The mod itself does not provide any help texts, just the framework. -It is the heart of the Help modpack, on which the other Help mods depend. - -Current version: 1.2.1 - -## For players -### Accessing the help -To open the help, there are multiple ways: - -- Use the `/helpform` chat command. This works always. -- If you use one of these mods, there's a help button in the inventory menu: - - Unified Inventory [`unified_inventory`] - - Simple Fast Inventory Buttons [`sfinv_buttons`] - - Inventory++ [`inventory_plus`] - -The help itself should be more or less self-explanatory. - -This mod is useless on its own, you will only need this mod as a dependency -for mods which actually add some help entries. - -### Hidden entries -Some entries are initially hidden from you. You can't see them until you -unlocked them. Mods can decide for themselves how particular entries are -revealed. Normally you just have to proceed in the game to unlock more -entries. Hidden entries exist to avoid spoilers and give players a small -sense of progress. - -Players with the `help_reveal` privilege can use the `/help_reveal` chat -command to reveal all hidden entries instantly. - -### Maintenance -The information of which player has viewed and revealed which entries is -stored in the world directory in the file `doc.mt`. You can safely reset -the viewed/revealed state of all players by deleting this file. Players -then need to start over revealing all entries. - -## For modders and game authors -This mod helps you in creating extensive and flexible help entries for your -mods or game. You can write about basically anything in the presentation -you prefer. - -To get started, read `API.md` in the directory of this mod. - -Note: If you want to add help texts for items and nodes, refer to the API -documentation of `doc_items`, instead of manually adding entries. -For custom entities, you may also want to add support for `doc_identifier`. - -## License of everything -MIT License diff --git a/doc/init.lua b/doc/init.lua deleted file mode 100644 index 9c612b3..0000000 --- a/doc/init.lua +++ /dev/null @@ -1,1220 +0,0 @@ -local S = minetest.get_translator("doc") -local F = function(f) return minetest.formspec_escape(S(f)) end - --- Compability for 0.4.14 or earlier -local colorize -if minetest.colorize then - colorize = minetest.colorize -else - colorize = function(color, text) return text end -end - -doc = {} - --- Some informational variables --- DO NOT CHANGE THEM AFTERWARDS AT RUNTIME! - --- Version number (follows the SemVer specification 2.0.0) -doc.VERSION = {} -doc.VERSION.MAJOR = 1 -doc.VERSION.MINOR = 2 -doc.VERSION.PATCH = 1 -doc.VERSION.STRING = doc.VERSION.MAJOR.."."..doc.VERSION.MINOR.."."..doc.VERSION.PATCH - --- Formspec information -doc.FORMSPEC = {} --- Width of formspec -doc.FORMSPEC.WIDTH = 15 -doc.FORMSPEC.HEIGHT = 10.5 - ---[[ Recommended bounding box coordinates for widgets to be placed in entry pages. Make sure -all entry widgets are completely inside these coordinates to avoid overlapping. ]] -doc.FORMSPEC.ENTRY_START_X = 0.2 -doc.FORMSPEC.ENTRY_START_Y = 0.5 -doc.FORMSPEC.ENTRY_END_X = doc.FORMSPEC.WIDTH -doc.FORMSPEC.ENTRY_END_Y = doc.FORMSPEC.HEIGHT - 0.5 -doc.FORMSPEC.ENTRY_WIDTH = doc.FORMSPEC.ENTRY_END_X - doc.FORMSPEC.ENTRY_START_X -doc.FORMSPEC.ENTRY_HEIGHT = doc.FORMSPEC.ENTRY_END_Y - doc.FORMSPEC.ENTRY_START_Y - ---TODO: Use container formspec element later - --- Internal helper variables -local DOC_INTRO = S("This is the help.") - -local COLOR_NOT_VIEWED = "#00FFFF" -- cyan -local COLOR_VIEWED = "#FFFFFF" -- white -local COLOR_HIDDEN = "#999999" -- gray -local COLOR_ERROR = "#FF0000" -- red - -local CATEGORYFIELDSIZE = { - WIDTH = math.ceil(doc.FORMSPEC.WIDTH / 4), - HEIGHT = math.floor(doc.FORMSPEC.HEIGHT-1), -} - -doc.data = {} -doc.data.categories = {} -doc.data.aliases = {} --- Default order (includes categories of other mods from the Docuentation System modpack) -doc.data.category_order = {"basics", "nodes", "tools", "craftitems", "advanced"} -doc.data.category_count = 0 -doc.data.players = {} - --- Space for additional APIs -doc.sub = {} - --- Status variables -local set_category_order_was_called = false - --- Returns the entry definition and true entry ID of an entry, taking aliases into account -local function get_entry(category_id, entry_id) - local category = doc.data.categories[category_id] - local entry - if category ~= nil then - entry = category.entries[entry_id] - end - if category == nil or entry == nil then - local c_alias = doc.data.aliases[category_id] - if c_alias then - local alias = c_alias[entry_id] - if alias then - category_id = alias.category_id - entry_id = alias.entry_id - category = doc.data.categories[category_id] - if category then - entry = category.entries[entry_id] - else - return nil - end - else - return nil - end - else - return nil - end - end - return entry, category_id, entry_id -end - ---[[ Core API functions ]] - --- Add a new category -function doc.add_category(id, def) - if doc.data.categories[id] == nil and id ~= nil then - doc.data.categories[id] = {} - doc.data.categories[id].entries = {} - doc.data.categories[id].entry_count = 0 - doc.data.categories[id].hidden_count = 0 - doc.data.categories[id].def = def - -- Determine order position - local order_id = nil - for i=1,#doc.data.category_order do - if doc.data.category_order[i] == id then - order_id = i - break - end - end - if order_id == nil then - table.insert(doc.data.category_order, id) - doc.data.categories[id].order_position = #doc.data.category_order - else - doc.data.categories[id].order_position = order_id - end - doc.data.category_count = doc.data.category_count + 1 - return true - else - return false - end -end - --- Add a new entry -function doc.add_entry(category_id, entry_id, def) - local cat = doc.data.categories[category_id] - if cat ~= nil then - local hidden = def.hidden or (def.hidden == nil and cat.def.hide_entries_by_default) - if hidden then - cat.hidden_count = cat.hidden_count + 1 - def.hidden = hidden - end - cat.entry_count = doc.data.categories[category_id].entry_count + 1 - if def.name == nil or def.name == "" then - minetest.log("warning", "[doc] Nameless entry added. Entry ID: "..entry_id) - end - cat.entries[entry_id] = def - return true - else - return false - end -end - --- Marks a particular entry as viewed by a certain player, which also --- automatically reveals it -function doc.mark_entry_as_viewed(playername, category_id, entry_id) - local entry, category_id, entry_id = get_entry(category_id, entry_id) - if not entry then - return - end - if doc.data.players[playername].stored_data.viewed[category_id] == nil then - doc.data.players[playername].stored_data.viewed[category_id] = {} - doc.data.players[playername].stored_data.viewed_count[category_id] = 0 - end - if doc.entry_exists(category_id, entry_id) and doc.data.players[playername].stored_data.viewed[category_id][entry_id] ~= true then - doc.data.players[playername].stored_data.viewed[category_id][entry_id] = true - doc.data.players[playername].stored_data.viewed_count[category_id] = doc.data.players[playername].stored_data.viewed_count[category_id] + 1 - -- Needed because viewed entries get a different color - doc.data.players[playername].entry_textlist_needs_updating = true - end - doc.mark_entry_as_revealed(playername, category_id, entry_id) -end - --- Marks a particular entry as revealed/unhidden by a certain player -function doc.mark_entry_as_revealed(playername, category_id, entry_id) - local entry, category_id, entry_id = get_entry(category_id, entry_id) - if not entry then - return - end - if doc.data.players[playername].stored_data.revealed[category_id] == nil then - doc.data.players[playername].stored_data.revealed[category_id] = {} - doc.data.players[playername].stored_data.revealed_count[category_id] = doc.get_entry_count(category_id) - doc.data.categories[category_id].hidden_count - end - if doc.entry_exists(category_id, entry_id) and entry.hidden and doc.data.players[playername].stored_data.revealed[category_id][entry_id] ~= true then - doc.data.players[playername].stored_data.revealed[category_id][entry_id] = true - doc.data.players[playername].stored_data.revealed_count[category_id] = doc.data.players[playername].stored_data.revealed_count[category_id] + 1 - -- Needed because a new entry is added to the list of visible entries - doc.data.players[playername].entry_textlist_needs_updating = true - -- Notify player of entry revelation - if doc.data.players[playername].stored_data.notify_on_reveal == true then - if minetest.get_modpath("central_message") ~= nil then - local cat = doc.data.categories[category_id] - cmsg.push_message_player(minetest.get_player_by_name(playername), S("New help entry unlocked: @1 > @2", cat.def.name, entry.name)) - end - -- To avoid sound spamming, don't play sound more than once per second - local last_sound = doc.data.players[playername].last_reveal_sound - if last_sound == nil or os.difftime(os.time(), last_sound) >= 1 then - -- Play notification sound - minetest.sound_play({ name = "doc_reveal", gain = 0.2 }, { to_player = playername }) - doc.data.players[playername].last_reveal_sound = os.time() - end - end - end -end - --- Reveal -function doc.mark_all_entries_as_revealed(playername) - -- Has at least 1 new entry been revealed? - local reveal1 = false - for category_id, category in pairs(doc.data.categories) do - if doc.data.players[playername].stored_data.revealed[category_id] == nil then - doc.data.players[playername].stored_data.revealed[category_id] = {} - doc.data.players[playername].stored_data.revealed_count[category_id] = doc.get_entry_count(category_id) - doc.data.categories[category_id].hidden_count - end - for entry_id, _ in pairs(category.entries) do - if doc.data.players[playername].stored_data.revealed[category_id][entry_id] ~= true then - doc.data.players[playername].stored_data.revealed[category_id][entry_id] = true - doc.data.players[playername].stored_data.revealed_count[category_id] = doc.data.players[playername].stored_data.revealed_count[category_id] + 1 - reveal1 = true - end - end - end - - local msg - if reveal1 then - -- Needed because new entries are added to player's view on entry list - doc.data.players[playername].entry_textlist_needs_updating = true - - msg = S("All help entries revealed!") - - -- Play notification sound (ignore sound limit intentionally) - minetest.sound_play({ name = "doc_reveal", gain = 0.2 }, { to_player = playername }) - doc.data.players[playername].last_reveal_sound = os.time() - else - msg = S("All help entries are already revealed.") - end - -- Notify - if minetest.get_modpath("central_message") ~= nil then - cmsg.push_message_player(minetest.get_player_by_name(playername), msg) - else - minetest.chat_send_player(playername, msg) - end -end - --- Returns true if the specified entry has been viewed by the player -function doc.entry_viewed(playername, category_id, entry_id) - local entry, category_id, entry_id = get_entry(category_id, entry_id) - if doc.data.players[playername].stored_data.viewed[category_id] == nil then - return false - else - return doc.data.players[playername].stored_data.viewed[category_id][entry_id] == true - end -end - --- Returns true if the specified entry is hidden from the player -function doc.entry_revealed(playername, category_id, entry_id) - local entry, category_id, entry_id = get_entry(category_id, entry_id) - local hidden = doc.data.categories[category_id].entries[entry_id].hidden - if doc.data.players[playername].stored_data.revealed[category_id] == nil then - return not hidden - else - if hidden then - return doc.data.players[playername].stored_data.revealed[category_id][entry_id] == true - else - return true - end - end -end - --- Returns category definition -function doc.get_category_definition(category_id) - if doc.data.categories[category_id] == nil then - return nil - end - return doc.data.categories[category_id].def -end - --- Returns entry definition -function doc.get_entry_definition(category_id, entry_id) - if not doc.entry_exists(category_id, entry_id) then - return nil - end - local entry, _, _ = get_entry(category_id, entry_id) - return entry -end - --- Opens the main documentation formspec for the player -function doc.show_doc(playername) - if doc.get_category_count() <= 0 then - minetest.show_formspec(playername, "doc:error_no_categories", doc.formspec_error_no_categories()) - return - end - local formspec = doc.formspec_core()..doc.formspec_main(playername) - minetest.show_formspec(playername, "doc:main", formspec) -end - --- Opens the documentation formspec for the player at the specified category -function doc.show_category(playername, category_id) - if doc.get_category_count() <= 0 then - minetest.show_formspec(playername, "doc:error_no_categories", doc.formspec_error_no_categories()) - return - end - doc.data.players[playername].catsel = nil - doc.data.players[playername].category = category_id - doc.data.players[playername].entry = nil - local formspec = doc.formspec_core(2)..doc.formspec_category(category_id, playername) - minetest.show_formspec(playername, "doc:category", formspec) -end - --- Opens the documentation formspec for the player showing the specified entry in a category -function doc.show_entry(playername, category_id, entry_id, ignore_hidden) - if doc.get_category_count() <= 0 then - minetest.show_formspec(playername, "doc:error_no_categories", doc.formspec_error_no_categories()) - return - end - local entry, category_id, entry_id = get_entry(category_id, entry_id) - if ignore_hidden or doc.entry_revealed(playername, category_id, entry_id) then - local playerdata = doc.data.players[playername] - playerdata.category = category_id - playerdata.entry = entry_id - - doc.mark_entry_as_viewed(playername, category_id, entry_id) - playerdata.entry_textlist_needs_updating = true - doc.generate_entry_list(category_id, playername) - - playerdata.catsel = playerdata.catsel_list[entry_id] - playerdata.galidx = 1 - - local formspec = doc.formspec_core(3)..doc.formspec_entry(category_id, entry_id, playername) - minetest.show_formspec(playername, "doc:entry", formspec) - else - minetest.show_formspec(playername, "doc:error_hidden", doc.formspec_error_hidden(category_id, entry_id)) - end -end - --- Returns true if and only if: --- * The specified category exists --- * This category contains the specified entry --- Aliases are taken into account -function doc.entry_exists(category_id, entry_id) - return get_entry(category_id, entry_id) ~= nil -end - --- Sets the order of categories in the category list -function doc.set_category_order(categories) - local reverse_categories = {} - for cid=1,#categories do - reverse_categories[categories[cid]] = cid - end - doc.data.category_order = categories - for cid, cat in pairs(doc.data.categories) do - if reverse_categories[cid] == nil then - table.insert(doc.data.category_order, cid) - end - end - reverse_categories = {} - for cid=1, #doc.data.category_order do - reverse_categories[categories[cid]] = cid - end - - for cid, cat in pairs(doc.data.categories) do - cat.order_position = reverse_categories[cid] - end - if set_category_order_was_called then - minetest.log("warning", "[doc] doc.set_category_order was called again!") - end - set_category_order_was_called = true -end - --- Adds an alias for an entry. Attempting to open an entry by an alias name --- results in opening the entry of the original name. -function doc.add_entry_alias(category_id_orig, entry_id_orig, category_id_alias, entry_id_alias) - if not doc.data.aliases[category_id_alias] then - doc.data.aliases[category_id_alias] = {} - end - doc.data.aliases[category_id_alias][entry_id_alias] = { category_id = category_id_orig, entry_id = entry_id_orig } -end - --- Returns number of categories -function doc.get_category_count() - return doc.data.category_count -end - --- Returns number of entries in category -function doc.get_entry_count(category_id) - return doc.data.categories[category_id].entry_count -end - --- Returns how many entries have been viewed by the player -function doc.get_viewed_count(playername, category_id) - local playerdata = doc.data.players[playername] - if playerdata == nil then - return nil - end - local count = playerdata.stored_data.viewed_count[category_id] - if count == nil then - playerdata.stored_data.viewed[category_id] = {} - count = 0 - playerdata.stored_data.viewed_count[category_id] = count - return count - else - return count - end -end - --- Returns how many entries have been revealed by the player -function doc.get_revealed_count(playername, category_id) - local playerdata = doc.data.players[playername] - if playerdata == nil then - return nil - end - local count = playerdata.stored_data.revealed_count[category_id] - if count == nil then - playerdata.stored_data.revealed[category_id] = {} - count = doc.get_entry_count(category_id) - doc.data.categories[category_id].hidden_count - playerdata.stored_data.revealed_count[category_id] = count - return count - else - return count - end -end - --- Returns how many entries are hidden from the player -function doc.get_hidden_count(playername, category_id) - local playerdata = doc.data.players[playername] - if playerdata == nil then - return nil - end - local total = doc.get_entry_count(category_id) - local rcount = playerdata.stored_data.revealed_count[category_id] - if rcount == nil then - return total - else - return total - rcount - end -end - --- Returns the currently viewed entry and/or category of the player -function doc.get_selection(playername) - local playerdata = doc.data.players[playername] - if playerdata ~= nil then - local cat = playerdata.category - if cat then - local entry = playerdata.entry - if entry then - return cat, entry - else - return cat - end - else - return nil - end - else - return nil - end -end - --- Template function templates, to be used for build_formspec in doc.add_category -doc.entry_builders = {} - --- Scrollable freeform text -doc.entry_builders.text = function(data) - local formstring = doc.widgets.text(data, doc.FORMSPEC.ENTRY_START_X, doc.FORMSPEC.ENTRY_START_Y, doc.FORMSPEC.ENTRY_WIDTH - 0.4, doc.FORMSPEC.ENTRY_HEIGHT) - return formstring -end - --- Scrollable freeform text with an optional standard gallery (3 rows, 3:2 aspect ratio) -doc.entry_builders.text_and_gallery = function(data, playername) - -- How much height the image gallery “steals” from the text widget - local stolen_height = 0 - local formstring = "" - -- Only add the gallery if images are in the data, otherwise, the text widget gets all of the space - if data.images ~= nil then - local gallery - gallery, stolen_height = doc.widgets.gallery(data.images, playername, nil, doc.FORMSPEC.ENTRY_END_Y + 0.2, nil, nil, nil, nil, false) - formstring = formstring .. gallery - end - formstring = formstring .. doc.widgets.text(data.text, - doc.FORMSPEC.ENTRY_START_X, - doc.FORMSPEC.ENTRY_START_Y, - doc.FORMSPEC.ENTRY_WIDTH - 0.4, - doc.FORMSPEC.ENTRY_HEIGHT - stolen_height) - - return formstring -end - -doc.widgets = {} - --- Scrollable freeform text -doc.widgets.text = function(data, x, y, width, height) - if x == nil then - x = doc.FORMSPEC.ENTRY_START_X - end - -- Offset to table[], which was used for this in a previous version - local xfix = x + 0.35 - if y == nil then - y = doc.FORMSPEC.ENTRY_START_Y - end - if width == nil then - width = doc.FORMSPEC.ENTRY_WIDTH - end - if height == nil then - height = doc.FORMSPEC.ENTRY_HEIGHT - end - -- Weird offset for textarea[] - local heightfix = height + 1 - - -- Also add background box - local formstring = "box["..tostring(x-0.175)..","..tostring(y)..";"..tostring(width)..","..tostring(height)..";#000000]" .. - "textarea["..tostring(xfix)..","..tostring(y)..";"..tostring(width)..","..tostring(heightfix)..";;;"..minetest.formspec_escape(data).."]" - return formstring -end - --- Image gallery --- Currently, only one gallery per entry is supported. TODO: Add support for multiple galleries in an entry (low priority) -doc.widgets.gallery = function(imagedata, playername, x, y, aspect_ratio, width, rows, align_left, align_top) - if playername == nil then return nil end -- emergency exit - - local formstring = "" - - -- Defaults - if x == nil then - if align_left == false then - x = doc.FORMSPEC.ENTRY_END_X - else - x = doc.FORMSPEC.ENTRY_START_X - end - end - if y == nil then - if align_top == false then - y = doc.FORMSPEC.ENTRY_END_Y - else - y = doc.FORMSPEC.ENTRY_START_Y - end - end - if width == nil then width = doc.FORMSPEC.ENTRY_WIDTH end - if rows == nil then rows = 3 end - - if align_left == false then - x = x - width - end - - local imageindex = doc.data.players[playername].galidx - doc.data.players[playername].maxgalidx = #imagedata - doc.data.players[playername].galrows = rows - - if aspect_ratio == nil then aspect_ratio = (2/3) end - local pos = 0 - local totalimagewidth, iw, ih - local bw = 0.5 - local buttonoffset = 0 - if #imagedata > rows then - totalimagewidth = width - bw*2 - iw = totalimagewidth / rows - ih = iw * aspect_ratio - if align_top == false then - y = y - ih - end - - local tt - if imageindex > 1 then - formstring = formstring .. "button["..x..","..y..";"..bw..","..ih..";doc_button_gallery_prev;"..F("<").."]" - if rows == 1 then - tt = F("Show previous image") - else - tt = F("Show previous gallery page") - end - formstring = formstring .. "tooltip[doc_button_gallery_prev;"..tt.."]" - end - if (imageindex + rows) <= #imagedata then - local rightx = buttonoffset + (x + rows * iw) - formstring = formstring .. "button["..rightx..","..y..";"..bw..","..ih..";doc_button_gallery_next;"..F(">").."]" - if rows == 1 then - tt = F("Show next image") - else - tt = F("Show next gallery page") - end - formstring = formstring .. "tooltip[doc_button_gallery_next;"..tt.."]" - end - buttonoffset = bw - else - totalimagewidth = width - iw = totalimagewidth / rows - ih = iw * aspect_ratio - if align_top == false then - y = y - ih - end - end - for i=imageindex, math.min(#imagedata, (imageindex-1)+rows) do - local xoffset = buttonoffset + (x + pos * iw) - local nx = xoffset - 0.2 - local ny = y - 0.05 - if imagedata[i].imagetype == "item" then - formstring = formstring .. "item_image["..xoffset..","..y..";"..iw..","..ih..";"..imagedata[i].image.."]" - else - formstring = formstring .. "image["..xoffset..","..y..";"..iw..","..ih..";"..imagedata[i].image.."]" - end - formstring = formstring .. "label["..nx..","..ny..";"..i.."]" - pos = pos + 1 - end - local bw, bh - - return formstring, ih -end - --- Direct formspec -doc.entry_builders.formspec = function(data) - return data -end - ---[[ Internal stuff ]] - --- Loading and saving player data -do - local filepath = minetest.get_worldpath().."/doc.mt" - local file = io.open(filepath, "r") - if file then - minetest.log("action", "[doc] doc.mt opened.") - local string = file:read() - io.close(file) - if(string ~= nil) then - local savetable = minetest.deserialize(string) - for name, players_stored_data in pairs(savetable.players_stored_data) do - doc.data.players[name] = {} - doc.data.players[name].stored_data = players_stored_data - end - minetest.log("action", "[doc] doc.mt successfully read.") - end - end -end - -function doc.save_to_file() - local savetable = {} - savetable.players_stored_data = {} - for name, playerdata in pairs(doc.data.players) do - savetable.players_stored_data[name] = playerdata.stored_data - end - - local savestring = minetest.serialize(savetable) - - local filepath = minetest.get_worldpath().."/doc.mt" - local file = io.open(filepath, "w") - if file then - file:write(savestring) - io.close(file) - minetest.log("action", "[doc] Wrote player data into "..filepath..".") - else - minetest.log("error", "[doc] Failed to write player data into "..filepath..".") - end -end - -minetest.register_on_leaveplayer(function(player) - doc.save_to_file() -end) - -minetest.register_on_shutdown(function() - minetest.log("action", "[doc] Server shuts down. Player data is about to be saved.") - doc.save_to_file() -end) - ---[[ Functions for internal use ]] - -function doc.formspec_core(tab) - if tab == nil then tab = 1 else tab = tostring(tab) end - return "size["..doc.FORMSPEC.WIDTH..","..doc.FORMSPEC.HEIGHT.."]tabheader[0,0;doc_header;".. - minetest.formspec_escape(S("Category list")) .. "," .. - minetest.formspec_escape(S("Entry list")) .. "," .. - minetest.formspec_escape(S("Entry")) .. ";" - ..tab..";false;false]" - -- Let the Game decide on the style, such as background, etc. -end - -function doc.formspec_main(playername) - local formstring = "textarea[0.35,0;"..doc.FORMSPEC.WIDTH..",1;;;"..minetest.formspec_escape(DOC_INTRO) .. "\n" - local notify_checkbox_x, notify_checkbox_y - if doc.get_category_count() >= 1 then - formstring = formstring .. F("Please select a category you wish to learn more about:").."]" - if doc.get_category_count() <= (CATEGORYFIELDSIZE.WIDTH * CATEGORYFIELDSIZE.HEIGHT) then - local y = 1 - local x = 1 - -- Show all categories in order - for c=1,#doc.data.category_order do - local id = doc.data.category_order[c] - local data = doc.data.categories[id] - local bw = doc.FORMSPEC.WIDTH / math.floor(((doc.data.category_count-1) / CATEGORYFIELDSIZE.HEIGHT)+1) - -- Skip categories which do not exist - if data ~= nil then - -- Category buton - local button = "button["..((x-1)*bw)..","..y..";"..bw..",1;doc_button_category_"..id..";"..minetest.formspec_escape(data.def.name).."]" - local tooltip = "" - -- Optional description - if data.def.description ~= nil then - tooltip = "tooltip[doc_button_category_"..id..";"..minetest.formspec_escape(data.def.description).."]" - end - formstring = formstring .. button .. tooltip - y = y + 1 - if y > CATEGORYFIELDSIZE.HEIGHT then - x = x + 1 - y = 1 - end - end - end - notify_checkbox_x = 0 - notify_checkbox_y = doc.FORMSPEC.HEIGHT-0.5 - else - formstring = formstring .. "textlist[0,1;"..(doc.FORMSPEC.WIDTH-0.2)..","..(doc.FORMSPEC.HEIGHT-2)..";doc_mainlist;" - for c=1,#doc.data.category_order do - local id = doc.data.category_order[c] - local data = doc.data.categories[id] - formstring = formstring .. minetest.formspec_escape(data.def.name) - if c < #doc.data.category_order then - formstring = formstring .. "," - end - end - local sel = doc.data.categories[doc.data.players[playername].category] - if sel ~= nil then - formstring = formstring .. ";" - formstring = formstring .. doc.data.categories[doc.data.players[playername].category].order_position - end - formstring = formstring .. "]" - formstring = formstring .. "button[0,"..(doc.FORMSPEC.HEIGHT-1)..";3,1;doc_button_goto_category;"..F("Show category").."]" - notify_checkbox_x = 3.5 - notify_checkbox_y = doc.FORMSPEC.HEIGHT-1 - end - local text - if minetest.get_modpath("central_message") then - text = F("Notify me when new help is available") - else - text = F("Play notification sound when new help is available") - end - formstring = formstring .. "checkbox["..notify_checkbox_x..","..notify_checkbox_y..";doc_setting_notify_on_reveal;"..text..";".. - tostring(doc.data.players[playername].stored_data.notify_on_reveal == true) .. "]" - else - formstring = formstring .. "]" - end - return formstring -end - -function doc.formspec_error_no_categories() - local formstring = "size[8,6]textarea[0.25,0;8,6;;" - formstring = formstring .. - minetest.formspec_escape( - colorize(COLOR_ERROR, S("Error: No help available.")) .. "\n\n" .. -S("No categories have been registered, but they are required to provide help.").."\n".. -S("The Documentation System [doc] does not come with help contents on its own, it needs additional mods to add help content. Please make sure such mods are enabled on for this world, and try again.")) .. "\n\n" .. -S("Recommended mods: doc_basics, doc_items, doc_identifier, doc_encyclopedia.") - formstring = formstring .. ";]button_exit[3,5;2,1;okay;"..F("OK").."]" - return formstring -end - -function doc.formspec_error_hidden(category_id, entry_id) - local formstring = "size[8,6]textarea[0.25,0;8,6;;" - formstring = formstring .. minetest.formspec_escape( - colorize(COLOR_ERROR, S("Error: Access denied.")) .. "\n\n" .. - S("Access to the requested entry has been denied; this entry is secret. You may unlock access by progressing in the game. Figure out on your own how to unlock this entry.")) - formstring = formstring .. ";]button_exit[3,5;2,1;okay;"..F("OK").."]" - return formstring -end - -function doc.generate_entry_list(cid, playername) - local formstring - if doc.data.players[playername].entry_textlist == nil - or doc.data.players[playername].catsel_list == nil - or doc.data.players[playername].category ~= cid - or doc.data.players[playername].entry_textlist_needs_updating == true then - local entry_textlist = "textlist[0,1;"..(doc.FORMSPEC.WIDTH-0.2)..","..(doc.FORMSPEC.HEIGHT-2)..";doc_catlist;" - local counter = 0 - doc.data.players[playername].entry_ids = {} - local entries = doc.get_sorted_entry_names(cid) - doc.data.players[playername].catsel_list = {} - for i=1, #entries do - local eid = entries[i] - local edata = doc.data.categories[cid].entries[eid] - if doc.entry_revealed(playername, cid, eid) then - table.insert(doc.data.players[playername].entry_ids, eid) - doc.data.players[playername].catsel_list[eid] = counter + 1 - -- Colorize entries based on viewed status - local viewedprefix = COLOR_NOT_VIEWED - local name = edata.name - if name == nil or name == "" then - name = S("Nameless entry (@1)", eid) - if doc.entry_viewed(playername, cid, eid) then - viewedprefix = "#FF4444" - else - viewedprefix = COLOR_ERROR - end - elseif doc.entry_viewed(playername, cid, eid) then - viewedprefix = COLOR_VIEWED - end - entry_textlist = entry_textlist .. viewedprefix .. minetest.formspec_escape(name) .. "," - counter = counter + 1 - end - end - if counter >= 1 then - entry_textlist = string.sub(entry_textlist, 1, #entry_textlist-1) - end - local catsel = doc.data.players[playername].catsel - if catsel then - entry_textlist = entry_textlist .. ";"..catsel - end - entry_textlist = entry_textlist .. "]" - doc.data.players[playername].entry_textlist = entry_textlist - formstring = entry_textlist - doc.data.players[playername].entry_textlist_needs_updating = false - else - formstring = doc.data.players[playername].entry_textlist - end - return formstring -end - -function doc.get_sorted_entry_names(cid) - local sort_table = {} - local entry_table = {} - local cat = doc.data.categories[cid] - local used_eids = {} - -- Helper function to extract the entry ID out of the output table - local extract = function(entry_table) - local eids = {} - for k,v in pairs(entry_table) do - local eid = v.eid - table.insert(eids, eid) - end - return eids - end - -- Predefined sorting - if cat.def.sorting == "custom" then - for i=1,#cat.def.sorting_data do - local new_entry = table.copy(cat.entries[cat.def.sorting_data[i]]) - new_entry.eid = cat.def.sorting_data[i] - table.insert(entry_table, new_entry) - used_eids[cat.def.sorting_data[i]] = true - end - end - for eid,entry in pairs(cat.entries) do - local new_entry = table.copy(entry) - new_entry.eid = eid - if not used_eids[eid] then - table.insert(entry_table, new_entry) - end - table.insert(sort_table, entry.name) - end - if cat.def.sorting == "custom" then - return extract(entry_table) - else - table.sort(sort_table) - end - local reverse_sort_table = table.copy(sort_table) - for i=1, #sort_table do - reverse_sort_table[sort_table[i]] = i - end - local comp - if cat.def.sorting ~= "nosort" then - -- Sorting by user function - if cat.def.sorting == "function" then - comp = cat.def.sorting_data - -- Alphabetic sorting - elseif cat.def.sorting == "abc" or cat.def.sorting == nil then - comp = function(e1, e2) - if reverse_sort_table[e1.name] < reverse_sort_table[e2.name] then return true else return false end - end - end - table.sort(entry_table, comp) - end - - return extract(entry_table) -end - -function doc.formspec_category(id, playername) - local formstring - if id == nil then - formstring = "label[0,0;"..F("Help > (No Category)") .. "]" - formstring = formstring .. "label[0,0.5;"..F("You haven't chosen a category yet. Please choose one in the category list first.").."]" - formstring = formstring .. "button[0,1;3,1;doc_button_goto_main;"..F("Go to category list").."]" - else - formstring = "label[0,0;"..minetest.formspec_escape(S("Help > @1", doc.data.categories[id].def.name)).."]" - local total = doc.get_entry_count(id) - if total >= 1 then - local revealed = doc.get_revealed_count(playername, id) - if revealed == 0 then - formstring = formstring .. "label[0,0.5;"..minetest.formspec_escape(S("Currently all entries in this category are hidden from you.").."\n"..S("Unlock new entries by progressing in the game.")).."]" - formstring = formstring .. "button[0,1.5;3,1;doc_button_goto_main;"..F("Go to category list").."]" - else - formstring = formstring .. "label[0,0.5;"..F("This category has the following entries:").."]" - formstring = formstring .. doc.generate_entry_list(id, playername) - formstring = formstring .. "button[0,"..(doc.FORMSPEC.HEIGHT-1)..";3,1;doc_button_goto_entry;"..F("Show entry").."]" - formstring = formstring .. "label["..(doc.FORMSPEC.WIDTH-4)..","..(doc.FORMSPEC.HEIGHT-1)..";"..minetest.formspec_escape(S("Number of entries: @1", total)).."\n" - local viewed = doc.get_viewed_count(playername, id) - local hidden = total - revealed - local new = total - viewed - hidden - -- TODO/FIXME: Check if number of hidden/viewed entries is always correct - if viewed < total then - formstring = formstring .. colorize(COLOR_NOT_VIEWED, minetest.formspec_escape(S("New entries: @1", new))) - if hidden > 0 then - formstring = formstring .. "\n" - formstring = formstring .. colorize(COLOR_HIDDEN, minetest.formspec_escape(S("Hidden entries: @1", hidden))).."]" - else - formstring = formstring .. "]" - end - else - formstring = formstring .. F("All entries read.").."]" - end - end - else - formstring = formstring .. "label[0,0.5;"..F("This category is empty.").."]" - formstring = formstring .. "button[0,1.5;3,1;doc_button_goto_main;"..F("Go to category list").."]" - end - end - return formstring -end - -function doc.formspec_entry_navigation(category_id, entry_id) - if doc.get_entry_count(category_id) < 1 then - return "" - end - local formstring = "" - formstring = formstring .. "button["..(doc.FORMSPEC.WIDTH-2)..","..(doc.FORMSPEC.HEIGHT-0.5)..";1,1;doc_button_goto_prev;"..F("<").."]" - formstring = formstring .. "button["..(doc.FORMSPEC.WIDTH-1)..","..(doc.FORMSPEC.HEIGHT-0.5)..";1,1;doc_button_goto_next;"..F(">").."]" - formstring = formstring .. "tooltip[doc_button_goto_prev;"..F("Show previous entry").."]" - formstring = formstring .. "tooltip[doc_button_goto_next;"..F("Show next entry").."]" - return formstring -end - -function doc.formspec_entry(category_id, entry_id, playername) - local formstring - if category_id == nil then - formstring = "label[0,0;"..F("Help > (No Category)") .. "]" - formstring = formstring .. "label[0,0.5;"..F("You haven't chosen a category yet. Please choose one in the category list first.").."]" - formstring = formstring .. "button[0,1;3,1;doc_button_goto_main;"..F("Go to category list").."]" - elseif entry_id == nil then - formstring = "label[0,0;"..minetest.formspec_escape(S("Help > @1 > (No Entry)", doc.data.categories[category_id].def.name)) .. "]" - if doc.get_entry_count(category_id) >= 1 then - formstring = formstring .. "label[0,0.5;"..F("You haven't chosen an entry yet. Please choose one in the entry list first.").."]" - formstring = formstring .. "button[0,1.5;3,1;doc_button_goto_category;"..F("Go to entry list").."]" - else - formstring = formstring .. "label[0,0.5;"..F("This category does not have any entries.").."]" - formstring = formstring .. "button[0,1.5;3,1;doc_button_goto_main;"..F("Go to category list").."]" - end - else - - local category = doc.data.categories[category_id] - local entry = get_entry(category_id, entry_id) - local ename = entry.name - if ename == nil or ename == "" then - ename = S("Nameless entry (@1)", entry_id) - end - formstring = "label[0,0;"..minetest.formspec_escape(S("Help > @1 > @2", category.def.name, ename)).."]" - formstring = formstring .. category.def.build_formspec(entry.data, playername) - formstring = formstring .. doc.formspec_entry_navigation(category_id, entry_id) - end - return formstring -end - -function doc.process_form(player,formname,fields) - local playername = player:get_player_name() - --[[ process clicks on the tab header ]] - if(formname == "doc:main" or formname == "doc:category" or formname == "doc:entry") then - if fields.doc_header ~= nil then - local tab = tonumber(fields.doc_header) - local formspec, subformname, contents - local cid, eid - cid = doc.data.players[playername].category - eid = doc.data.players[playername].entry - if(tab==1) then - contents = doc.formspec_main(playername) - subformname = "main" - elseif(tab==2) then - contents = doc.formspec_category(cid, playername) - subformname = "category" - elseif(tab==3) then - doc.data.players[playername].galidx = 1 - contents = doc.formspec_entry(cid, eid, playername) - if cid ~= nil and eid ~= nil then - doc.mark_entry_as_viewed(playername, cid, eid) - end - subformname = "entry" - end - formspec = doc.formspec_core(tab)..contents - minetest.show_formspec(playername, "doc:" .. subformname, formspec) - return - end - end - if(formname == "doc:main") then - for cid,_ in pairs(doc.data.categories) do - if fields["doc_button_category_"..cid] then - doc.data.players[playername].catsel = nil - doc.data.players[playername].category = cid - doc.data.players[playername].entry = nil - doc.data.players[playername].entry_textlist_needs_updating = true - local formspec = doc.formspec_core(2)..doc.formspec_category(cid, playername) - minetest.show_formspec(playername, "doc:category", formspec) - break - end - end - if fields["doc_mainlist"] then - local event = minetest.explode_textlist_event(fields["doc_mainlist"]) - local cid = doc.data.category_order[event.index] - if cid ~= nil then - if event.type == "CHG" then - doc.data.players[playername].catsel = nil - doc.data.players[playername].category = cid - doc.data.players[playername].entry = nil - doc.data.players[playername].entry_textlist_needs_updating = true - elseif event.type == "DCL" then - doc.data.players[playername].catsel = nil - doc.data.players[playername].category = cid - doc.data.players[playername].entry = nil - doc.data.players[playername].entry_textlist_needs_updating = true - local formspec = doc.formspec_core(2)..doc.formspec_category(cid, playername) - minetest.show_formspec(playername, "doc:category", formspec) - end - end - end - if fields["doc_button_goto_category"] then - local cid = doc.data.players[playername].category - doc.data.players[playername].catsel = nil - doc.data.players[playername].entry = nil - doc.data.players[playername].entry_textlist_needs_updating = true - local formspec = doc.formspec_core(2)..doc.formspec_category(cid, playername) - minetest.show_formspec(playername, "doc:category", formspec) - end - if fields["doc_setting_notify_on_reveal"] then - doc.data.players[playername].stored_data.notify_on_reveal = fields["doc_setting_notify_on_reveal"] == "true" - end - elseif(formname == "doc:category") then - if fields["doc_button_goto_entry"] then - local cid = doc.data.players[playername].category - if cid ~= nil then - local eid = nil - local eids, catsel = doc.data.players[playername].entry_ids, doc.data.players[playername].catsel - if eids ~= nil and catsel ~= nil then - eid = eids[catsel] - end - doc.data.players[playername].galidx = 1 - local formspec = doc.formspec_core(3)..doc.formspec_entry(cid, eid, playername) - minetest.show_formspec(playername, "doc:entry", formspec) - doc.mark_entry_as_viewed(playername, cid, eid) - end - end - if fields["doc_button_goto_main"] then - local formspec = doc.formspec_core(1)..doc.formspec_main(playername) - minetest.show_formspec(playername, "doc:main", formspec) - end - if fields["doc_catlist"] then - local event = minetest.explode_textlist_event(fields["doc_catlist"]) - if event.type == "CHG" then - doc.data.players[playername].catsel = event.index - doc.data.players[playername].entry = doc.data.players[playername].entry_ids[event.index] - doc.data.players[playername].entry_textlist_needs_updating = true - elseif event.type == "DCL" then - local cid = doc.data.players[playername].category - local eid = nil - local eids, catsel = doc.data.players[playername].entry_ids, event.index - if eids ~= nil and catsel ~= nil then - eid = eids[catsel] - end - doc.mark_entry_as_viewed(playername, cid, eid) - doc.data.players[playername].entry_textlist_needs_updating = true - doc.data.players[playername].galidx = 1 - local formspec = doc.formspec_core(3)..doc.formspec_entry(cid, eid, playername) - minetest.show_formspec(playername, "doc:entry", formspec) - end - end - elseif(formname == "doc:entry") then - if fields["doc_button_goto_main"] then - local formspec = doc.formspec_core(1)..doc.formspec_main(playername) - minetest.show_formspec(playername, "doc:main", formspec) - elseif fields["doc_button_goto_category"] then - local formspec = doc.formspec_core(2)..doc.formspec_category(doc.data.players[playername].category, playername) - minetest.show_formspec(playername, "doc:category", formspec) - elseif fields["doc_button_goto_next"] then - if doc.data.players[playername].catsel == nil then return end -- emergency exit - local eids = doc.data.players[playername].entry_ids - local cid = doc.data.players[playername].category - local new_catsel= doc.data.players[playername].catsel + 1 - local new_eid = eids[new_catsel] - if #eids > 1 and new_catsel <= #eids then - doc.mark_entry_as_viewed(playername, cid, new_eid) - doc.data.players[playername].catsel = new_catsel - doc.data.players[playername].entry = new_eid - doc.data.players[playername].galidx = 1 - local formspec = doc.formspec_core(3)..doc.formspec_entry(cid, new_eid, playername) - minetest.show_formspec(playername, "doc:entry", formspec) - end - elseif fields["doc_button_goto_prev"] then - if doc.data.players[playername].catsel == nil then return end -- emergency exit - local eids = doc.data.players[playername].entry_ids - local cid = doc.data.players[playername].category - local new_catsel= doc.data.players[playername].catsel - 1 - local new_eid = eids[new_catsel] - if #eids > 1 and new_catsel >= 1 then - doc.mark_entry_as_viewed(playername, cid, new_eid) - doc.data.players[playername].catsel = new_catsel - doc.data.players[playername].entry = new_eid - doc.data.players[playername].galidx = 1 - local formspec = doc.formspec_core(3)..doc.formspec_entry(cid, new_eid, playername) - minetest.show_formspec(playername, "doc:entry", formspec) - end - elseif fields["doc_button_gallery_prev"] then - local cid, eid = doc.get_selection(playername) - if doc.data.players[playername].galidx - doc.data.players[playername].galrows > 0 then - doc.data.players[playername].galidx = doc.data.players[playername].galidx - doc.data.players[playername].galrows - end - local formspec = doc.formspec_core(3)..doc.formspec_entry(cid, eid, playername) - minetest.show_formspec(playername, "doc:entry", formspec) - elseif fields["doc_button_gallery_next"] then - local cid, eid = doc.get_selection(playername) - if doc.data.players[playername].galidx + doc.data.players[playername].galrows <= doc.data.players[playername].maxgalidx then - doc.data.players[playername].galidx = doc.data.players[playername].galidx + doc.data.players[playername].galrows - end - local formspec = doc.formspec_core(3)..doc.formspec_entry(cid, eid, playername) - minetest.show_formspec(playername, "doc:entry", formspec) - end - else - if fields["doc_inventory_plus"] and minetest.get_modpath("inventory_plus") then - doc.show_doc(playername) - return - end - end -end - -minetest.register_on_player_receive_fields(doc.process_form) - -minetest.register_chatcommand("helpform", { - params = "", - description = S("Open a window providing help entries about Minetest and more"), - privs = {}, - func = function(playername, param) - doc.show_doc(playername) - end, - } -) - -minetest.register_on_joinplayer(function(player) - local playername = player:get_player_name() - local playerdata = doc.data.players[playername] - if playerdata == nil then - -- Initialize player data - doc.data.players[playername] = {} - playerdata = doc.data.players[playername] - -- Gallery index, stores current index of first displayed image in a gallery - playerdata.galidx = 1 - -- Maximum gallery index (index of last image in gallery) - playerdata.maxgalidx = 1 - -- Number of rows in an gallery of the current entry - playerdata.galrows = 1 - -- Table for persistant data - playerdata.stored_data = {} - -- Contains viewed entries - playerdata.stored_data.viewed = {} - -- Count viewed entries - playerdata.stored_data.viewed_count = {} - -- Contains revealed/unhidden entries - playerdata.stored_data.revealed = {} - -- Count revealed entries - playerdata.stored_data.revealed_count = {} - else - -- Completely rebuild viewed and revealed counts from scratch - for cid, cat in pairs(doc.data.categories) do - if playerdata.stored_data.viewed[cid] == nil then - playerdata.stored_data.viewed[cid] = {} - end - if playerdata.stored_data.revealed[cid] == nil then - playerdata.stored_data.revealed[cid] = {} - end - local vc = 0 - local rc = doc.get_entry_count(cid) - doc.data.categories[cid].hidden_count - for eid, entry in pairs(cat.entries) do - if playerdata.stored_data.viewed[cid][eid] then - vc = vc + 1 - playerdata.stored_data.revealed[cid][eid] = true - end - if playerdata.stored_data.revealed[cid][eid] and entry.hidden then - rc = rc + 1 - end - end - playerdata.stored_data.viewed_count[cid] = vc - playerdata.stored_data.revealed_count[cid] = rc - end - end - - -- Add button for Inventory++ - if minetest.get_modpath("inventory_plus") ~= nil then - inventory_plus.register_button(player, "doc_inventory_plus", S("Help")) - end -end) - ----[[ Add buttons for inventory mods ]] -local button_action = function(player) - doc.show_doc(player:get_player_name()) -end - --- Unified Inventory -if minetest.get_modpath("unified_inventory") ~= nil then - unified_inventory.register_button("doc", { - type = "image", - image = "doc_button_icon_hires.png", - tooltip = S("Help"), - action = button_action, - }) -end - --- sfinv_buttons -if minetest.get_modpath("sfinv_buttons") ~= nil then - sfinv_buttons.register_button("doc", { - image = "doc_button_icon_lores.png", - tooltip = S("Collection of help texts"), - title = S("Help"), - action = button_action, - }) -end - - -minetest.register_privilege("help_reveal", { - description = S("Allows you to reveal all hidden help entries with /help_reveal"), - give_to_singleplayer = false -}) - -minetest.register_chatcommand("help_reveal", { - params = "", - description = S("Reveal all hidden help entries to you"), - privs = { help_reveal = true }, - func = function(name, param) - doc.mark_all_entries_as_revealed(name) - end, -}) diff --git a/doc/locale/doc.de.tr b/doc/locale/doc.de.tr deleted file mode 100644 index 39fc725..0000000 --- a/doc/locale/doc.de.tr +++ /dev/null @@ -1,51 +0,0 @@ -# textdomain:doc -<=< ->=> -Access to the requested entry has been denied; this entry is secret. You may unlock access by progressing in the game. Figure out on your own how to unlock this entry.=Der Zugriff auf den angeforderten Eintrag wurde verweigert; dieser Eintrag ist geheim. Sie können durch weiteren Spielfortschritt den Zugriff freischalten. Finden Sie selbst heraus, wie Sie diesen Eintrag freischalten können. -All entries read.=Alle Einträge gelesen. -All help entries revealed!=Alle Hilfseinträge aufgedeckt! -All help entries are already revealed.=Alle Hilfseinträge sind schon aufgedeckt. -Allows you to reveal all hidden help entries with /help_reveal=Ermöglicht es Ihnen, alle verborgenen Hilfseinträge mit /help_reveal freizuschalten -Category list=Kategorienliste -Currently all entries in this category are hidden from you.=Momentan sind alle Einträge in dieser Kategorie vor Ihnen verborgen. -Unlock new entries by progressing in the game.=Schalten Sie neue Einträge frei, indem Sie im Spiel fortschreiten. -Help=Hilfe -Entry=Eintrag -Entry list=Eintragsliste -Error: Access denied.=Fehler: Zugriff verweigert. -Error: No help available.=Fehler: Keine Hilfe verfügbar. -Go to category list=Zur Kategorienliste -Go to entry list=Zur Eintragsliste -Help > (No Category)=Hilfe > (Keine Kategorie) -Help > @1=Hilfe > @1 -Help > @1 > @2=Hilfe > @1 > @2 -Help > @1 > (No Entry)=Hilfe > @1 > (Kein Eintrag) -Hidden entries: @1=Verborgene Einträge: @1 -New entries: @1=Neue Einträge: @1 -New help entry unlocked: @1 > @2=Neuen Hilfseintrag freigeschaltet: @1 > @2 -No categories have been registered, but they are required to provide help.=Es wurden keine Kategorien registriert, aber sie werden benötigt, um die Hilfe anbieten zu können. -The Documentation System [doc] does not come with help contents on its own, it needs additional mods to add help content. Please make sure such mods are enabled on for this world, and try again.=Das Dokumentationssystem [doc] bringt von sich aus keine eigenen Hilfsinhalte mit, es benötigt zusätzliche Mods, um sie hinzuzufügen. Bitte stellen Sie sicher, dass solche Mods für diese Welt aktiviert sind und versuchen Sie es erneut. -Number of entries: @1=Anzahl der Einträge: @1 -OK=OK -Open a window providing help entries about Minetest and more=Ein Fenster mit Hilfseinträgen über Minetest und mehr öffnen -Please select a category you wish to learn more about:=Bitte wählen Sie eine Kategorie, über die Sie mehr erfahren möchten, aus: -Recommended mods: doc_basics, doc_items, doc_identifier, doc_encyclopedia.=Empfohlene Mods: doc_basics, doc_items, doc_identifier, doc_encyclopedia. -Reveal all hidden help entries to you=Alle für Sie verborgenen Hilfseinträge freischalten -Show entry=Eintrag zeigen -Show category=Kategorie zeigen -Show next entry=Nächsten Eintrag zeigen -Show previous entry=Vorherigen Eintrag zeigen -This category does not have any entries.=Diese Kategorie hat keine Einträge. -This category has the following entries:=Diese Kategorie hat die folgenden Einträge: -This category is empty.=Diese Kategorie ist leer. -This is the help.=Dies ist die Hilfe. -You haven't chosen a category yet. Please choose one in the category list first.=Sie haben noch keine Kategorie gewählt, Bitte wählen Sie zuerst eine aus. -You haven't chosen an entry yet. Please choose one in the entry list first.=Sie haben noch keinen Eintrag gewählt. Bitte wählen Sie zuerst einen aus. -Nameless entry (@1)=Namenloser Eintrag (@1) -Collection of help texts=Sammlung von Hilfstexten -Notify me when new help is available=Benachrichtigen, wenn neue Hilfe verfügbar ist -Play notification sound when new help is available=Toneffekt abspielen, wenn neue Hilfe verfügbar ist -Show previous image=Vorheriges Bild zeigen -Show previous gallery page=Vorherige Galerieseite zeigen -Show next image=Nächstes Bild zeigen -Show next gallery page=Nächste Galerieseite zeigen diff --git a/doc/locale/doc.pt.tr b/doc/locale/doc.pt.tr deleted file mode 100644 index 52d6836..0000000 --- a/doc/locale/doc.pt.tr +++ /dev/null @@ -1,43 +0,0 @@ -# textdomain:doc -<= ->= -Access to the requested entry has been denied; this entry is secret. You may unlock access by progressing in the game. Figure out on your own how to unlock this entry.=O acesso à entrada solicitada foi negado; essa entrada é secreta. Você pode desbloquear o acesso progredindo no jogo. Descobrir por conta própria como desbloquear essa entrada. -All entries read.=Todas as entradas lidas. -All help entries revealed!=Todas as entradas de ajuda reveladas! -All help entries are already revealed.=Todas as entradas de ajuda já foram reveladas. -Allows you to reveal all hidden help entries with /help_reveal=Permite revelar todas as entradas de ajuda ocultas com /help_reveal -Category list=Lista de Categorias -Currently all entries in this category are hidden from you.\\nUnlock new entries by progressing in the game.=Atualmente, todas as entradas nessa categoria estão ocultas a você.\\nDesbloqueie novas entradas progredindo no jogo. -Help=Ajuda -Entry=Entrada -Entry list=Lista de Entradas -Error: Access denied.=Erro: Acesso negado. -Error: No help available.=Erro: Nenhuma ajuda disponível. -Go to category list=Ver categorias -Go to entry list=Ir para a lista de entradas -Help > @1=Ajuda > @1 -Help > @1 > @2=Ajuda > @1 > @2 -Help > @1 > (No Entry)=Ajuda > @1 > (Nenhuma Entrada) -Help > (No Category)=Ajuda > (Nenhuma Categoria) -Hidden entries: @1=Entradas ocultas: @1 -Nameless entry (@1)=Entrada sem nome (@1) -New entries: @1=Novas entradas: (@1) -New help entry unlocked: @1 > @2=Nova entrada de ajuda desbloqueada: @1 > @2 -No categories have been registered, but they are required to provide help.\nThe Documentation System [doc] does not come with help contents on its own, it needs additional mods to add help content. Please make sure such mods are enabled on for this world, and try again.=Nenhuma categoria foi registrada, mas é necessário fornecer ajuda.\nO Sistema de Documentação [doc] não vem com o conteúdo de ajuda, ele precisa de mods adicionais para adicionar conteúdo de ajuda. Por favor, certifique-se de que os mods estão habilitados para este mundo e tente novamente. -Number of entries: @1=Número de entradas: @1 -OK=OK -Open a window providing help entries about Minetest and more=Abra uma janela fornecendo entradas de ajuda sobre o Minetest e mais -Please select a category you wish to learn more about:=Por favor, selecione uma categoria sobre a qual você deseja saber mais: -Recommended mods: doc_basics, doc_items, doc_identifier, doc_encyclopedia.=Mods recomendados: doc_basics, doc_items, doc_identifier, doc_encyclopedia. -Reveal all hidden help entries to you=Revela todas as entradas de ajuda ocultas para você -Show entry=Ver entrada -Show category=Ver categoria -Show next entry=Ver próxima entrada -Show previous entry=Ver entrada anterior -This category does not have any entries.=Essa categoria não possui entradas. -This category has the following entries:=Essa categoria tem as seguintes entradas: -This category is empty.=Essa categoria está vazia. -This is the help.=Essa é a ajuda. -You haven't chosen a category yet. Please choose one in the category list first.=Você ainda não escolheu uma categoria. Por favor, escolha uma na lista de categorias primeiro. -You haven't chosen an entry yet. Please choose one in the entry list first.=Você ainda não escolheu uma entrada. Por favor, escolha uma na lista de entrada primeiro. -Collection of help texts=Coleção de textos de ajuda diff --git a/doc/locale/doc.pt_BR.tr b/doc/locale/doc.pt_BR.tr deleted file mode 100644 index 52d6836..0000000 --- a/doc/locale/doc.pt_BR.tr +++ /dev/null @@ -1,43 +0,0 @@ -# textdomain:doc -<= ->= -Access to the requested entry has been denied; this entry is secret. You may unlock access by progressing in the game. Figure out on your own how to unlock this entry.=O acesso à entrada solicitada foi negado; essa entrada é secreta. Você pode desbloquear o acesso progredindo no jogo. Descobrir por conta própria como desbloquear essa entrada. -All entries read.=Todas as entradas lidas. -All help entries revealed!=Todas as entradas de ajuda reveladas! -All help entries are already revealed.=Todas as entradas de ajuda já foram reveladas. -Allows you to reveal all hidden help entries with /help_reveal=Permite revelar todas as entradas de ajuda ocultas com /help_reveal -Category list=Lista de Categorias -Currently all entries in this category are hidden from you.\\nUnlock new entries by progressing in the game.=Atualmente, todas as entradas nessa categoria estão ocultas a você.\\nDesbloqueie novas entradas progredindo no jogo. -Help=Ajuda -Entry=Entrada -Entry list=Lista de Entradas -Error: Access denied.=Erro: Acesso negado. -Error: No help available.=Erro: Nenhuma ajuda disponível. -Go to category list=Ver categorias -Go to entry list=Ir para a lista de entradas -Help > @1=Ajuda > @1 -Help > @1 > @2=Ajuda > @1 > @2 -Help > @1 > (No Entry)=Ajuda > @1 > (Nenhuma Entrada) -Help > (No Category)=Ajuda > (Nenhuma Categoria) -Hidden entries: @1=Entradas ocultas: @1 -Nameless entry (@1)=Entrada sem nome (@1) -New entries: @1=Novas entradas: (@1) -New help entry unlocked: @1 > @2=Nova entrada de ajuda desbloqueada: @1 > @2 -No categories have been registered, but they are required to provide help.\nThe Documentation System [doc] does not come with help contents on its own, it needs additional mods to add help content. Please make sure such mods are enabled on for this world, and try again.=Nenhuma categoria foi registrada, mas é necessário fornecer ajuda.\nO Sistema de Documentação [doc] não vem com o conteúdo de ajuda, ele precisa de mods adicionais para adicionar conteúdo de ajuda. Por favor, certifique-se de que os mods estão habilitados para este mundo e tente novamente. -Number of entries: @1=Número de entradas: @1 -OK=OK -Open a window providing help entries about Minetest and more=Abra uma janela fornecendo entradas de ajuda sobre o Minetest e mais -Please select a category you wish to learn more about:=Por favor, selecione uma categoria sobre a qual você deseja saber mais: -Recommended mods: doc_basics, doc_items, doc_identifier, doc_encyclopedia.=Mods recomendados: doc_basics, doc_items, doc_identifier, doc_encyclopedia. -Reveal all hidden help entries to you=Revela todas as entradas de ajuda ocultas para você -Show entry=Ver entrada -Show category=Ver categoria -Show next entry=Ver próxima entrada -Show previous entry=Ver entrada anterior -This category does not have any entries.=Essa categoria não possui entradas. -This category has the following entries:=Essa categoria tem as seguintes entradas: -This category is empty.=Essa categoria está vazia. -This is the help.=Essa é a ajuda. -You haven't chosen a category yet. Please choose one in the category list first.=Você ainda não escolheu uma categoria. Por favor, escolha uma na lista de categorias primeiro. -You haven't chosen an entry yet. Please choose one in the entry list first.=Você ainda não escolheu uma entrada. Por favor, escolha uma na lista de entrada primeiro. -Collection of help texts=Coleção de textos de ajuda diff --git a/doc/locale/template.txt b/doc/locale/template.txt deleted file mode 100644 index fdeecfd..0000000 --- a/doc/locale/template.txt +++ /dev/null @@ -1,51 +0,0 @@ -# textdomain:doc -<= ->= -Access to the requested entry has been denied; this entry is secret. You may unlock access by progressing in the game. Figure out on your own how to unlock this entry.= -All entries read.= -All help entries revealed!= -All help entries are already revealed.= -Allows you to reveal all hidden help entries with /help_reveal= -Category list= -Currently all entries in this category are hidden from you. -Unlock new entries by progressing in the game.= -Help= -Entry= -Entry list= -Error: Access denied.= -Error: No help available.= -Go to category list= -Go to entry list= -Help > @1= -Help > @1 > @2= -Help > @1 > (No Entry)= -Help > (No Category)= -Hidden entries: @1= -Nameless entry (@1)= -New entries: @1= -New help entry unlocked: @1 > @2= -No categories have been registered, but they are required to provide help.= -The Documentation System [doc] does not come with help contents on its own, it needs additional mods to add help content. Please make sure such mods are enabled on for this world, and try again.= -Number of entries: @1= -OK= -Open a window providing help entries about Minetest and more= -Please select a category you wish to learn more about:= -Recommended mods: doc_basics, doc_items, doc_identifier, doc_encyclopedia.= -Reveal all hidden help entries to you= -Show entry= -Show category= -Show next entry= -Show previous entry= -This category does not have any entries.= -This category has the following entries:= -This category is empty.= -This is the help.= -You haven't chosen a category yet. Please choose one in the category list first.= -You haven't chosen an entry yet. Please choose one in the entry list first.= -Collection of help texts= -Notify me when new help is available= -Play notification sound when new help is available= -Show previous image= -Show previous gallery page= -Show next image= -Show next gallery page= diff --git a/doc/mod.conf b/doc/mod.conf deleted file mode 100644 index 302fd83..0000000 --- a/doc/mod.conf +++ /dev/null @@ -1,3 +0,0 @@ -name = doc -optional_depends = unified_inventory, sfinv_buttons, central_message, inventory_plus -description = A simple in-game documentation system which enables mods to add help entries based on templates. diff --git a/doc/screenshot.png b/doc/screenshot.png deleted file mode 100644 index 90946a9999d0558787fb1a7d3d6fdbfa56a92fb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12315 zcmYjXWmFtpl*HZLo!}ZExD(uhI|L`VOM(vW9z1Ap1_%U~!GjY#xVyV<^X>lFIfr4o zd#3yKefQR_s@IWfDzfM(Bq&f&Q0Ve<(x0H9pjm;>gGeyI`*OSD+dpWxPqLCw)njD) zzy`9joSqvL6h`mcA9N}U1}U%;(Oq6y25}9Ii~x-RuQf3r*o9`Rsp~G~T6XnHRm=Y*SR4rSgxb~Zh(2q9ph$;B-zk0s^rzYAC4;o(8&5iqAI zWqgO%SBVrwCxZ=LkF>-8ek{f;>3vv+%g)NO*Xc>?<4eo%wujBBCBeScNyqr9M&4yv zwT2dh=C|?7X@Q>)&a=5MIw*LIBcInMn0|<_d%>A)P6Y5^yzU->5?}4f9>k_8@LoE@ zz#XsS#4~azK!;z);xFMmE) z_ysT;uYR+CN*}9milKZseGX5}adQ}s%v6@O=CjaoB(UO}wm->sM9)cr#8&tkYnbGl zG9o?p``eQ}&4mR8R2@Ipmey8mUR3lDnh=S(o4iKL2L9OH>HKBl%bUD@QSl%`dm@1> zD;tn)j4t~zAc6414B2zq0}8y9g!gW@*N2mUfV-)2k8fgl2NK>}7m6VHu3sjZ7*^!z zzt$)2cVBCAO{DftC_}fei2B+0PZ>}>TEmw^aN`YqMA|c5B%#(_gA;<+soI{`gg}Ut zVyB%?TGu5ihL3u?LhkE*6U&sUhIe;csT^ZV6G`vAca>KgC|d@MO`h*~Sx5H&iCxDO zT6Z3izvjR0#JA7+!)Z$0`iuH*YYl9t!~XUc^tqI+lzE}mG4_b-AR&4Dyw)Gx{*&S+ z=9T~Jt@7^PVMX54{QH}OcC6f%^SZ+&hU1W13^d`TfSdb#RE}D)(yhI|8cZYUC(D2E zY_1N34a4R-#@Qr~2lIW_kFp(RU;c5lAGJRe97AqTL!Gy7yh@49#=B@8v1UvmoMo#>7BB3!rtrK*5e&D|3qB(mOl7B zoO)z`YwGLK{BerGC&Lssm5|Kj>lYSYB9?RsmZ;is&uNghRj=N-gr zp!(~a-_6R*qsg(*<`o!p*=1X_=x)4KkJ4uV{>E4=hARMjd(^JT~YQVg&v-8z@MYsv1 zv_n+nVQ=m1@2x)MT-A8R|7zog&`HHOAkvP7&l7$1tN%@ZeGa+xN6L<+uUiMtvL@st z{$KBU_d3>V+_6?VJ#XvDMSiodJistI9=7=G929<>Aqf6u&$AN7+x|A8;7`fuZ_! zV%E!lcWAsu?8(>rNZtJ3-nE~}FU)Vg7Hbb{vAeA;1Ez||k|_01>p73ACnDain`6l} z9X<JZ)tq z*2d5Mjx}z5^d1;u_&_1t{&jb_g!aQAc`@e~EEP~9>Kq0I`Mm4V?E2*@A7yh}#pzAl z$zfIdhYytPo@ZA*v52y!5$wy)JH7XhqmRB^H(vz!X5G(Nl~%_#y)d&MPrCn7W?|&c zc|50A4V-!y`*t|4$_+GI1N)Yz{fiy$&P(DdPCaB1`*X=fTuy9W`$E1I$|5*9*i#;M z+--FYwGM>WG~^KdTl6{ZY9`DReQBw6K*O*e2z9!>iSxoV{&La+KaJ_0XVmHi*ZS*m z`X|w{au}95Wb!fG@8hr3+tsB-PXwYK1+TcTZSBYIvafqLFXK+aFT>Swe~HX+KzLS^ zkXFoGJMw8n)rW!H5Q6p}?Nw85=h4ptVRi=N?uI_2Qwwa#>;J|Ne|sHMct735MXCg0OmjSt4;tq+@%6=LnA zafaXA+>g@D=llf(A1buS3&qG=Z+2BGpFLh~!#2HMM&EOi46i0NyB+PaE#Kb8e_a;f z^Vt4!YjTFBd;&Rn4$H(2+z5*!HJW=F@uwht6==5~Ek3vauMDN7pkr)1!mB zZX28+{qQXAeSDJ+M;*zNg@qBfB~_Nkqee#5f=!x! zbt4KFDb39dLSj&jkN%89=6;JKPd9Z6BS}b@URPJw*w`2q6;)7BFg5ilUu|z|t4Ndi z`1lwW7FJ41>Kxal*)T4mvokgwtUU48vr zVV@}-22#>2s+=@dJ=g1lnPSEC0u{~A*4DCBGBijH`c2MeIy&iPWwzelca0AJK7anK zU1MxyVluw%nw6Pp!A*Pt`(3L-`~3cCXJ;oR1uu+jV`XLKgVTy;nI=kTFk7OHr6v3n zyKx&*Zbf;yI0uqW#f<6oNXGlf$Vhs6dUSO3+S=M19zl9+5Z3qolasIvoJi^B=4MV8 zHa0ecM*ARmA&&!1b935H_6`ofY0<169v?qAEW(KfZD;a+QJXp6956dERZ-36uk|>b zWl+rx6xW61=2D=dqUz2S%Ekkc!oa{N@E0edq@*MyWWYi?I5+?!+i~JZl!jtaK}*hy z$9{y}@;qLIPma)XCh0iyDcIDDIv_=wAu4mzp2m^^IdgI3yGMS;_~ux zmHWZrA#7A2?hX$V(@;+j?7Q2gW;f0vczAelf}Wn~wdOD#! z$)|$CLTFMOC1vH%dl)Ci;B$&LwOU;?hGg{JK(ezC9b|rJW=>dpd$t2mpLwAKe=TFE zAlHjDg7;5n+2rJ8b+LmY1X^rRKS3p>RE{(a(khBv7Y#fjVoz{4RL3_j1FvDwa+2Bo zv4`&mNbk{#v>@E(5Dvps#x|%s`|kdvYBF+E882uQG?R08|J&2NASqG{ci8K)o_1<{ zXMcal@rmYr8!F)@g~VV62?FcP%h&%1v=Vsu{9>5E3FaW_dv8 zR;0s;dC=AAhvHyo#}NBFHHCwVo6c?|$jx16GfA@*E-T12-RnA@E3zlW7;GOJ8j9Nr z{hMG@N?Hw*W}f|H(V0%IK!bkllc=bujEu}6!mDgt26SV+#(&N1qkaj3FUg0;OtYiM0QR(=ur94KjNX&VOuj-(lkN3U&F-rwIZO-l?p%v30b`6nPC&_%kShCjw&C#7;0gYP0F3|#x8@v2CIC?pt;XiRcXV`I5xjqV+)Usy#GH$CWPPoszPe&r^?U6+&vx#M z!rx=r>1F>6zKt0uFs$UHjDz@@M4b z+JXWYL$k>0kf$zK0a8-Z$to5W7Ik?S7p@Ip`11sUlxaZ4Kv8HOt#(r85Rqf&V5UL^ zZV#u2(6CPaySTUr3lEN6#o3Azhfhrq> zHvbP65#z_tjR?~WXsBw8(b3VptB{b8AEjkwWhEt6+kaB$iSJ z@|m~NsI{@Y9K{;8&<3y913JUyj?wS#%#26Y#Dwyow`1M3cKLF5ybwPDI(4lnP=s09 z92?YWeZJfl zw6&tDDu?A34=NNZ#135lf&h09kNm$-3|?NhK|#=0@2^}fUPReJx8^qYc?Y#Kg ziSmr!;~=HESwNxt#WYeSMxjg0uHVs|!R%~-7sdckittvYWJ|$t_9Xvc(&h!B`a=;c zCr^X0w9WEdtP=z}rmDLG@l!4}7`bcN9#oSqJdQemPLFi(ShF0E4fhHR&i zXNj_Uis35y2L@`BNk2GBV`pns^1grHL)`tB9uRwX-T;RuR3Na_}{FCI9LT2b|gZW5?YE(h&q4sC9;I_FX4=n6AA|fK}g3xVYVF*{|cpz#Rx$W)ky@kDjCLXAm zn;XyRM$2IW(-@VQ4R9VIyW#f_P87b(ZHDgJeD)#4-Lf}FAYutUC|D2_#SNJ(h(B9iSJIH22sCdn9dit$t_F>S-K`F8hq;-nHtG?Oph)TK zL)t}wcd>Gwga&aAG6vH^sA);T1EOn9&V1r{7?dtpq2Ky*f8gNt8k?=E!6j_=ZqOh} z#U_VHd-6AZ>QWzIK4NZnx)P$qO*{1iJDzpAdAUP=OXP_k!k`fm)72q)n~M;+q{vV- zYAd##l!?r8=VF@?&wqnY3!qt6zg0?VcjzHgpG|(p7p`^Wg48-sOMY)gHUU4GI>|Iy zm1zB$MHgOk?Xd1o5XuOW5DM#pbM%aWnV=f1qILL?qboSaOfe1OI1m1fx56uQ8KP9v5D}9c<*bJnM@U1OE-Ow zFZ#+X%9b>VF%HNYD5Ujs9zXG_6e|{<#kz5l$eCLdrL`N-ZN1dD$yj0iW3kJB!AzyFx0r5dq-GVF@Gz*?A_)* ze$7O6b$J;b8Ht@JS7ggXMP)i!Ak*n7dtc7mesA!R8B=t`_#ac*JQqC3*w`2w8+)A& z$5#L1<|a(!>3UhcW(ge@|M65#;ln$^>gZ8p0eH~K$w_{GK6TN8wy7yqb(w^O#6!h| z_^C3(GsV{az5udh3^ILjRx&DSGU{v*9$$Zjjw&>D-nhxfOf6`!e6=RG-7x@=>*~1A z5DtKbkKL_bDM=?LMoDOt7AM`S2jV$&b#u#t%SRp8`fi-93I1qUN6pnqEo#k-)NEKS zW~&`))~w5FT>Ck+z5SbpMzS~+R8(Urg-}d3gs!jW^sAIHK=m@Li*(X+V6H`8@JV(H&R1w;0<5N-wJl&o1ewnpj zZov;zFVpmNcb}e_Nli&XLqjVnDS^lVVTKXrJ3Rs_)bHjf=uzRP>65{nutQMzymLnh-897LVuC7ji3wUu`ceanFLaqWDa{R4Y;+B6Vn{CVI&O<3`A|U z`!>(J@S!xyG{Hf4K!3?dOjOs@Oi4@Ye@Ukj5h2G=w6d}?HqO;#hED)Tfis%W-p;wO zu&{3c0aac|D~Ei(r`V2K7HDYw891@HnECt@)z*{u+=Sb{ajvMdKf_zVyx@L5g~hH_ zFFiJP)B?$;dTMGkbTkCs0HN;7?QRVqMyRBhrlzKXq-m6OsN}}UJ#?y<3iSe51Eh5N zcB9gIK0^z-gDsvo}Pmn9Z{9E+8?7DLy znXJiG&aAGT%2-ds_cN@7J5jDb=MNl`hUVlSZa6dTX3qLxD!RlNW?cvvPfOFcjH)mt zUk)otu0M1llrZT#J`=~JYbmSZNCgd&JY8Yb@TTI742+CzQ6;}%J06e9b9MqSQiF%Q z1vn75hnc&to|3jtLAkKLI`_3^NkT$`DKJnrA75X9Q#?KNqlt0z3dz*d7;9xD80D0f z&r0%p-(X0-u6~~;#mC2&r%5cKr=-l2uV>6|Zo6|=w(@Z(FA>$MSI`G1{pEW4bv+V& zZ0$ck_3H3lZe#7N!kUDFg2K$qEWc=hAS*kJg(Z`gib}jweGLpQ3oBYpHSK?=YPoR{ zdSR&LW2CK@TnSduG9K4+d#GWZ&bbqiOW{M7)X|xvnzCo1p(&`Yc08P|A|@ubnFcxv zzkt7>8Qb@(>uY5tC01r;h$>$!I#Xbp%5o(tte^;zkECr}fj2&t5=*%^a>*q&^hxbOXz5*rtQC2oR zJ)IVqa+oj3B>P9B|CJJ2x<$nw?Y@dMhO#fN%!fcW0a+H#^Dj6R)`~j=4GYo>EqSA* zeKxze7)8(i`~Lo3_us+-GGS?LEtiOh5gksq{nSF1kxTQE{At{0C8ES~g`tXB(Mp{Z z`Y(1Rfmj!GqvfVo8=ISeoHAV~FE8huMFc4neIo&!TIz0-~=$tg@6AJrHC@K@u^u9 zW;6%N{}ldJED22b7BmscQvstGO~A(e;lsdQ@Ut~?bq#nV^A3zmMe#6XSFFIYjBpD`iW|KBsI)Z7AQyyx6c5~U%>^xliGuzDr<%*qTf~tNWJm2W;bEjpYb=VZ0p`pP=*l z^thO*Tg+Ofm0peeB~9_7q(w+!wSgwl>gKNvyRd)3r$W}6an=e|Z5`{h8Rh4QU}>7s zqpuK~Nap$$zGi!^q!#8v3w#MV8e%_Dv$}Hev{qqWKbcRSTD~r9Z+qu(Tzy=kmSTca zBQvzlGw|zz@d5R2VXyc-Gc~WgEK&y=a*>jKz(n;6keCdKa(`2+s*a0>t{2686~@rg zcVsQ`WSF9QEbleM_ck|a@lXl@0sm|3^i*u$Z9yMNBX#o6hMcV#sFI3Kz#0V!AXPoU z3y99IBC)c$g-}wWEP@PeDme}e{N1o375MzDEYjzJ5j18-Mn*0!byk9(B_%YFjz*zc z6v_I&fq~8JdZuRFij~p+4OX!OGwd|(+HA%b$CpUy=LXh95}W?*_4WMMTY}+@DG1%Y zvvdy~i8DVu=&Pt$0*_m;8%^?%f}-MFl>y>B3=B+pMFl(zw6>+Cr7aH$A1RhF_%yHf zQOd259=!6PCB7$9;$>0--&&$i1f1Dg2=j7#?7#be! z?uH+yrKHf&)916I0NL`{8jMT_S&;D3>-g$pXh_yDIie8osiq#4gI^t+c@or(Rt)4hlZewd3kv&bZX)vBL#deijtFYgUuTJ`@37e)OT|V{4<7-u zEE`V|^y}fl_blGm?#mZ5C$X11^CL9>lYhT4_Y{ghO^c)RglwF9Kb+V&fAwur!lj-A z$-5Sov~h(XglQ;hytmc{tAkZ+a;vM^0X;SW|GrqeBIvWMtgN0M@mUY^4V$rAVonaa zH^9~tl^O9MamN7vPK7epm9)0D{xvx`h;-5A4|RtgI|EHnY`0`lxIHxBkUN zlB--G;n||yiMjxxGT#FjEzo^qV=CY%!LmMUH5>AFJ-nqZep}}#X3a_z`B4nz(Oeiw zKR-V&K#xtupp+mN0Z!0&+634YaeYNa)U}`hBw^ETaVExK`retVt{_-CSM$h+VrxLq|88NjLFFzC?;fInZRrXI}Vai(A)iztZA?3crwkk~p}7 zXwu{ijYWf<4ZB7znV_NS-3MQ3@=zk9wI2y{VphMJ~Gpa`5e2OV&gPiA2N^E-cWv)U|*>EoE-8>Vw4Sr z3QA&ACkduBdxJ{WiyzEs$wu|q`Lh{%?be@aP(O&%>7^yWn-eh&qbHaC%$*)y4CATK zhryr+Ze%e4|B^sv(KU_dvT;yiY}gX{Vnx?vfav0j&5%A+h7 zvgF6lvwpdL=&Bc28qdOjvgfuO9(Mq@)oG1JS3_9XW&^LP^XA{m;rY^ zMNaBnCa@`8q6WeQUMY+f|uimDlc~{ujKTJa+C$~m%h+uYT2ys+WGn6 z(>OUKD}7L@ArHwlQqtU+G7>bzn(T(TRJ^o;%CL$=>~qpZ+qi%!n7E7UYQCM}LL3T- zfiO0|wj1zeUT?Yn#zgjnHDx^NYm`E{9l%|y%jmA;seFrqv*#F0#FN%x_9V_YH^YE%N zGDRd4_Q|30{~Lb+fsc=}lwmm}%>m%v-o}>z=mCq9lhd;vUhPGtjb6T7d5D_!;DXDE zEI}q>UU;7zgT&s+$(U%L(t~qtjWHr3A}u#p{mtp_?d7EuoX%fNTlhu+K7lO#?!k+z ztLeOHQrb~G1=RI87|9<1Dgma^u-tpPfPhzg7VV;+KVjKY6|?}pmy;9gi89B;$%*w# zN!l4Zl$2XoI3^FEnQK@~_H}$L5TcJXX@enne3X=y#Q#pKQx%Gdv>EYG__hi62Zs*2 zT{jqpRoQq$0LJVWPoH8LX%Wgb1<}=0uWa*1`CtAW1~+c8JC*}<&)swHHM_@~V*mwz zU@OLcOioGp<$HZlP(TB?cG}U=(U#nLPEH(ZOJFmp|L7=1ljY_21Pw;KYLiY1%TxtR zeSLkvj|JSz{xiVtiHeWsU}d#f9sTG4*jIzenVG&(pNoMAjlJ!OEA`SV{EbMEq=feE8=)T0q=|D2YZ zYRk%y5x^xS2uMNIF)?Tf2%s)4dwbTlbbwI+@Uqb*re{UthmOz8tfs_^-MX@qDS2BKJ9 zT0+xT$rH`V%4&677QFJ~58{jghl3NqDqu-Y4Nh4;K0cc^z_U$(@rO!PhWSXw$Hu_G zARs`zwZ{C#(b0czg1RYD9F=es;DUhwXNg6p#)b#%?#s)|b$~dmWoY?t^dj4nob_nJ z=vYL@#PkwOo=oe$FTVZ8o|To5Mz6qv2&#=zFw^hD!&+QiypVrSrv^tFaY)i89do`W z6-=PZ#vkM?8$>w>9RzrVsi~>XLT0^dA{(Dj3K2EJgmqD~0}1TkA*4|e%c#MkQB{(S z&@zX|$}pM6JlVe!eUOlpgi#`ElF?!e{sZ*Q#$c^L+$I_ZyB?gLH=MVt%t*?~S*Al; zkLy=RmGtpxt9$pZompR-4<0l-JA2i)NsO2E9rE-PY2CyrVZ)pTp^=jY`OvV6DN3kl z+ihr}rJ?)GzlxaSR^p_^%FHj_N53rbegz@u#gjETo*#_8bo@^ZR#Jx;M%KSbCzM;FPPTUy!}4 zslAcU5>_vGC#Cq2(hrZLDWj#~?- zg6U+C-{_K-A%)5JOs0e#)K5GvQ%~MZdXhLpdueJ31z5$lIH`Tee+qP6W##E;qfZYq zOV#L$w&^VJklynoW(a7A+ep1h{G(IjRs8sY_+%#BdY+3X*L*|Tq%9YHj;CLjZG84Z zm&>aFQc^Yn(DP>9$-fHy*}PnjV@4U)KtcU{!3(K0R2fYiFBhWFY7k=$UT5*FH=dw7VDd@{ zSf#SMy1I-*rkUTphI>m;Rce^|jJ{vBCcW&|8F^Q~Bta&YT1uC~u(XUKTHmfSoMjn0MwBvLx@UA4@wm9S>|siO|Mmj#OP4i_G$aoi8v5nsrK6)` zFft-9k1{RdasSE@PQay#m4(F|_eMP%UjnYLmLSqTZB3e~5t*)Tgbo(@WRDJs+~{s; zo~F8Jh079O$8b1()+H^~gM;N1o&6M&(izt zNZtfFqXxuwo0hirJ32am=UM^lLb9>|lKjB2w>e$}7B(7eZEYpetl={suHnubh*Km^5aFS4S1y^%%=rRv2zrOxGdzvU+4;{30s$k>1f@~I2}t)fp%O50)Rq}7Ja!C#oyp!s5IOG-+v59ewOn*j}SdoWXB z>Uy~|steN=6@{XzI=(p&AM&raSGqwzCn*VLuJq^6@KNvJTA7{UbdG500>JGCrd7j$ zNY0Sm3kQTT_Vv)Yp#dD61tue7$4}{O00mhtL-&C}!SYyw2OY}t+#o0|Wo7gqFqoVg zUC3CFrXdS%=lR)LglrTP6me|RFHTOf23_k%hlf&nLPA1#aQa}YBies*l@%4{1o#NJ z8LBygeWIhW*`>mKe4Ybw zljYV#;ts|sOfvpJJY5-SFx=BL8A1}^$%=v+*9B$^6o&U)N#WG#8Nk1Uz?HJCtOAg~ zArt-m2sbGuRwR=AwSf9NGN04d*5;pycCY(uyABB*3_+9AYjI~XBoU7m23FnfA{*?h zGXY1O20*z8D$ELEu|#M~KyG472v%S*H5Gk^LO%Sd$-F=?DO1XZ#_&9DDb#Z2KvRu(Vieq#x zy}L&w%X$>4J+8Ly0GpRm)h1k;xzc>$wVYzyffT>>Sa$py)3d1)LiXZOFi!_VxNIAY zHWb2(w6X*1R=O^Xn+l=na}3*M@ve+maBQu_Vt3Xczayvl_s-muj2#F&gE!L}{%W)j z7`P3xSm#AM6}`}+07gt9F3LS07$jdoo~*t2uJTt*+4>otfln0M*FJ)3_x5BRB=O>U zX&Pb`eMO>FYtqi8cmAQ4N)5%}q)nQCYph1&sa0OsH69me?*KEXM{;lEH_CV|p4LLI zwt=(`D|U*Tcb$jl5V}ekI!0s#xo|KNfW{LirAC^$#YlW$7&83C zH{w5JG$Um!xDbyr!b=IM;j9-f-lBnoWyKcBs)uK6L7{Cypx?!X`H2l>h!69RK30O` z@a2DTmHM9F&WrMXkTu^{ygyicJJ>QKI)wY^?dM%}UOO50L&_nSBa%Ews68mZurlv{ zX2CHNvePO8H$frEumWR}A+MI}WAg$5OI8Wl9i&@r)NrCIeZWlkchR;-miQL#ofnk9 zKic5Cecmk=hna7r^UWF9Z7}4WvNgJ#7r6l$;H@-hbi~1nI>w7WW`vdUg(RgS)L9e> zlzhNayPZT&mxy*8=Q{eeuOvv%YPe1b=Dl)y88DWIVZyuN(I?Bdn8P6vJ`{a_upYS_ z@0#M_Og1M-usUEdSY!Bbo~r+*GuD?UL;cH2pcU#ZGcI9MBAj;~2RYwm@3KwCAvg29 z1FqqSOz2HNdZ{sTEuVE*@qIU|p9@ni>y#yHmnB4m&MQTlyNP~Uf`33ZDDg*R-scVz zLF?T3-ds@xt_!KJp$CFkYH=Fp7J$^l#A`Am=@g$lGMf z*kpPc)DT9*f*?Q$a}H^3Lk@vo`5Nx3hk>lJ`uaBW>#=wZF{+5!RSj z^mCyf3WSW~+|UYn_X}dg#r+}|bu)0u?&ZmQN8q#lnxWH>?8>LOvd*vT+v9Q$FgI~!)*OPyZ#-X5o-Nw3m32qf-FhcRM>?HD~T(X5m}R6&#Cr! zvS&z%EK)#~7z3Lh>BqXHo+HbgTUZaW-3hX_3exwpkvd_FwD9(to~Fe(8ifbtF8=uD zg?E?n@Q3hD{_Pg|PZ-J6HIAq0j~G}>UvI;G{k#{TQ}-?2T}7O&ZzhrwO%VScyv z-bEiJQ5@XNKS1UT`V&I6Q{ldvj79KT8Uf?(78;d{(d*q z;3cd4yxl_BGz2W^^b_G``u2`q6MP8|UD@yv{S@b8x)=;~%!-n!r%FRSN}jXJmVt=z z?H8Hripsm`j-HQBBMEZ-ffGwY>W_KcqEq+!c=Xup}Lng(3r{pzPZ;tJlEkN@@hez;)*nNFECToct5+ z8{6E}m0Y!WUq!6+ex|*x|31XvK&-jsX^7UNdX~KSEh({=Ch0V8oL5Xp`Cqp(h39k- z>XB&nV~O9UmmO*1p`hhw2zQ*G=|garyGD+a0)TNJ1D$J~rh>&oA>}kHK4}mjShAvgVn@@afp8h5nKddQ`^n{fq)m*Ww$AlP=%vw&1oNMeT&1TBK1!oB~6#N<*@uA5OE$avz;# ztAdMW6Yb!J&+MbY_HmY_Q{1e7xq1FF^Yr9mD(;E@1fCiy6|y6xsYe>tC#lxQ$qen9 zTuvR*ZDRcf9g7Ss9EjWCverkA)FNp>%fKCfh5Y`l@Lbe*bxZIzf?ueL_4r%*-L$cP zYGcP{USNNh1!Ugbw|8a(z5^ONVXip{B2nssWor-D%%?6u_Wou9>t;gr;|D7_I$H5P zyo_}`15=J^{wN;LNguLd@JMm~qA7N^+4yZf>H9ZC{)MiiE4#b!aaW)puc;T`wUSm- z+pN6UEQ5fW*wg(DM}$E)*!ztIU-=7W7k})4vx*cYwG<_}k9_{?9s-v~J@}rIu~k&* z@ZzQVWCezJDYf1ikhr(;IUyUtDWu=gASQ;vA5)63O?5P<)$%hg#~B;Y0+pU`Zh;UM ztilC<12JR+0q0x|Go^oviFpii&-)`8cxUM<+L^{lpX@$CnDs<DFT=-ynsped$msBVFd34so|-MBC-J&+{_`smvd4XyZ~ z;|Tu%zAJ82b7UXc+HX3|&|*v7v=ElJ4n`(f&6%8~)~m?4WtO2^^i8^!PD!Y2h>!bU z_spBggT~B2*kNGb_{9}jOdZiolFQmwx6uQ%Xq;e9nz%3b28zOaGjq07B9WEB*n$>^F@yIJrLYk zbvs{a!0_tEX&ESc-kO27Mbdh?V2&%4Gv^rj9X<9NcMAuo25c(#*db3vrrV?xKgB=a zEK>tHO;GbWS49QKCr9Jo0)$2#Pgw{9BEtH-&s4TH|M81GJc+KP!T%1A@sm#!i*R2m f#RiJ=T>$jLr^*JJU&SGB59-Uys7O~!ng;(5T<~}= diff --git a/doc/sounds/doc_reveal.ogg b/doc/sounds/doc_reveal.ogg deleted file mode 100644 index 3fbe176b6330bfa46b09bedc24d71b37e537e796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8873 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 diff --git a/doc/textures/doc_button_icon_hires.png b/doc/textures/doc_button_icon_hires.png deleted file mode 100644 index 25c9fe4e95cefa9dda2f5acc74b48dcf1ce4c014..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2336 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 Ef@YaF-v9sr diff --git a/doc/textures/inventory_plus_doc_inventory_plus.png b/doc/textures/inventory_plus_doc_inventory_plus.png deleted file mode 100644 index 3df6195c7f6e0f317daf6962008c56f782904512..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 722 zcmV;@0xkWCP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jB}5 z5jY04NYAbS00L4;L_t(I%dL~qOH%<9#(#IaU2U6b<|gV~qf%4~Ey)%PjZrWNNstId zVUPX~(o?-jU_JO2>|r%XdfLlgs+UDpv_^``nyH&5ZDQNJyVE&$d$?)NpqDz2=lj0H z;XB_EI9hIx3Frq#0Ozl62=D;`f?oMBT{t2hLJ*!}Yl994G`DK~L=@&{AifByI!w^( z-YgV^DMjBG*U5-<$O13dnbH+Imo%L2Rfi1TN_4G6=s8k@+}TPqw5wG zHK(YotHU<_O;uoP1Lzll5jq@Lj1mA=_ia#1RM}e(>`~Se0O&*!0EXH z)L!T*!;-mz7A)|IK!ErnIeCkeLBed%%vAS^H1ypBptO@mUugg!r4-1?TUsh1pd;v& zQPp9lCt1mElTx%z^2x6(`KMU&Pf^IG55z0kZJ3_ikF=~MF&3G_+9DDS_onTgWQqc6 zb`$y28vu@V^^({XN&QHJe*)6U`vkp@{>w87|N7290hmSd@&JoXkpKVy07*qoM6N<$ Ef@YaF-v9sr