--[[ Example for Documentation System [`doc`]. Reminder: This mod is the core of the Help modpack. It is thus rather low-level. Use this to add your very own categories and entries, and to use some utility functions. This example demonstrates how to add categories and how to add entries into them. It also demonstrates the versatility of the very important `build_formspec` function used in category definitions. ]] -- Let's start with a very simple text-based category. -- This category only contains simple text. doc.add_category("example1", { -- This name is for humans and mandatory name = "Example: Text", -- This category uses a preset formspec builder for simple text build_formspec = doc.entry_builders.text --[[ Reminder: build_formspec determines how the entry data will be presented to the user ]] }) doc.add_category("sexample", { name = "Example: Empty", }) -- Entries for the aforementioned category. We add 2 entries. doc.add_entry("example1", "text", { -- This is for the entry title in the user interface, it's mandatory. name = "Text example", -- For this category, the entry data is simply the text to be displayed data = "Lorem Minetest dolor sit amet. Bla bla bla bla Minetest bla bla bla bla Mese bla. Bla bla bla bla bla, celeron55 bla bla, bla.", }) -- We will use this entry in doc_identifier.lua doc.add_entry("example1", "entity", { name = "Entity entry", data = "This is the entry for the entity (added in doc_identifier.lua). The example entity is just a simple cube which floats in the air. Punch it to destroy it.", }) ------------------------------------------------------------------------------- --[[ Category with hidden entry. This is a category like the one before, but this time, we add a hidden entry. ]] doc.add_category("example_hide", { name = "Example: Hidden entry", build_formspec = doc.entry_builders.text }) -- This entry will start hidden. The user will not see it until it gets -- revealed by using doc.mark_entry_as_revealed. Note that you should -- NOT hide entries if there is no way for the player to reveal them. doc.add_entry("example_hide", "hidden", { name = "Hidden Entry", hidden = true, data = "This entry is hidden.", }) -- This chat command demonstrates how to use `doc.mark_entry_as_revealed`. minetest.register_chatcommand("doc_example_reveal", { param = "", description = "Reveal the hidden entry of the doc_example mod", privs = {}, func = function(playername, params) -- This reveals the previously created entry doc.mark_entry_as_revealed(playername, "example_hide", "hidden") minetest.chat_send_player(playername, "The hidden doc_example entry has been revealed! Look into the category “Example Hidden” to see it.") end, }) --[[ In actual games, you would probably want to invent more engaging ways to reveal entries. ;-) ]] ------------------------------------------------------------------------------- --[[ A simple category with 3 entries: Cities. Now we're getting somewhere! This time, we define a custom build_formspec function to display entry data dynamically. ]] doc.add_category("example2", { name = "Example: Cities", description = "Example category: Quick information about the cities of the world", --[[ This is a manual formspec builder: This will parse the entry data and turns it into nice formspec widgets. Reminder: We MUST return a valid formspec string! ]] build_formspec = function(data) return "label[0,1;Description: "..minetest.formspec_escape(data.description).."]" .. "label[0,2;Population: "..data.population.."]" end, --[[ ADVANCED: Sorting example ]] --[[ The entry data includes population as a number. This means we could (if we want to) define a custom sorting function. This affects the order of the entries. It makes sure that in the list of entries, the city with the highest population comes first. Custom sorting is entirely optional but it might make it easier for the user to navigate. But note that the default alphabetical sorting is often good as well. ]] sorting = "function", sorting_data = function(entry1, entry2) return entry1.data.population > entry2.data.population end, }) doc.add_entry("example2", "london", { name="London", -- Reminder: This data is put into the previous build_formspec function data = { description = "London is the capital of the United Kingdom.", population = 8538689, }, }) doc.add_entry("example2", "shanghai", { name="Shanghai", data = { description = "Shanghai lies in China and is one of the biggest cities in the world.", population = 23019148, }, }) doc.add_entry("example2", "tripoli", { name="Tripoli", data = { description = "Tripoli is the capital of Lybia.", population = 1780000, }, }) ------------------------------------------------------------------------------- --[[ Formspec category: This category shows how you can add widgets in entries and even interact with them ]] doc.add_category("example3", { name="Example: Formspec", description="Example category for manual free-form formspec entries", --[[ This is a built-in formspec builder. In this case, the entry data is expected to contains the full formspec definition for any entry. This is useful if you want to build every entry by hand. The downside is that it doesn't allow for dynamic entries. ]] build_formspec = doc.entry_builders.formspec, --[[ Sorting example ]] --[[ This demonstrates the custom sorting type. In the entry list, the entries will appear in the exact order as specified. ]] sorting = "custom", sorting_data = { "simple_bad", "simple_good", "multi", "testbutton" }, }) -- Just an entry with a label (BAD example) doc.add_entry("example3", "simple_bad", { name="Label", -- Please note the coordinates are shoddily chosen here, the don't respect -- the Documention System formspec boundaries at all, so this is just a guess. data = "label[5,5;Just a bad, bad label.]" }) -- Just an entry with a label (good example) doc.add_entry("example3", "simple_good", { name="Label", --[[ This is the proper way to add widgets (this is also how you should do it in build_formspec): Defining the coordinates relative to the Documentation System's boundaries. In this case, the label will be at the top right. ]] data = "label["..doc.FORMSPEC.ENTRY_START_X..","..doc.FORMSPEC.ENTRY_START_Y..";Just a good label.]" }) -- Now let's get crazy with MULTIPLE formspec entries. How awesome is that? doc.add_entry("example3", "multi", { name="Label", -- Label, just like before data = "label["..doc.FORMSPEC.ENTRY_START_X..","..doc.FORMSPEC.ENTRY_START_Y..";Just another label.]" .. -- Note the different Y offsets "button["..doc.FORMSPEC.ENTRY_START_X..","..(doc.FORMSPEC.ENTRY_START_Y + 1)..";5,1;example_useless;Useless button]" .. "button["..doc.FORMSPEC.ENTRY_START_X..","..(doc.FORMSPEC.ENTRY_START_Y + 2)..";5,1;example_useless;Useless button 2]" .. "button["..doc.FORMSPEC.ENTRY_START_X..","..(doc.FORMSPEC.ENTRY_START_Y + 3)..";5,1;example_useless;Useless button 3]" -- As you see, it's special at all. It's a normal formspec string, just longer. }) -- This entry will be interactive. doc.add_entry("example3", "testbutton", { name="Event Button", -- This button actually will be used for an event … data = "button["..doc.FORMSPEC.ENTRY_START_X..","..doc.FORMSPEC.ENTRY_START_Y..";5,1;example_button;Event]", }) -- … and here we react on the button event by writing something into the chat -- This demonstrates how you can use an entry widget for custom actions minetest.register_on_player_receive_fields(function(player, formname, fields) -- Condition 1: This checks if the player is even using the entry tab. -- This check is always the same. if formname == "doc:entry" then local playername = player:get_player_name() -- Condition 2: this check is required to make sure we “listen” -- to the correct entry local category_id, entry_id = doc.get_selection(playername) if category_id == "example3" and entry_id == "testbutton" then -- Condition 3: Has the widget we actually care about been pressed? if fields.example_button then -- All conditions are met! Now the custom action can be executed minetest.chat_send_player(playername, "You have pressed the event button!") end end end end) ------------------------------------------------------------------------------- --[[ This category demonstrates the use of the gallery widget. ]] -- FIXME: Depends on Minetest Game doc.add_category("example4", { name="Example: Galleries", build_formspec = function(data, playername) -- The trick here is to include doc.widgets.gallery into the custom -- build_formspec definition. local formspec = "" --[[ Mostly using default values, but we want an aspect ratio of 1:1 (square). ]] formspec = formspec .. doc.widgets.gallery(data, playername, nil, nil, 1) return formspec end, }) -- Several gallery entries doc.add_entry("example4", "gallery2", { name="Gallery with 2 images", -- The entry data will be also fed into `doc_widgets_gallery` data = { {image="default_grass.png"}, {image="default_book.png"} }, }) doc.add_entry("example4", "gallery3", { name="Gallery with 3 images", data = { {image="default_grass.png"}, {image="default_book.png"}, {image="default_papyrus.png"}}, }) --[[ The default gallery size is 3. But this gallery has 4 images. The Documentation System automatically adds “scroll buttons” if the number of images exceeds the gallery size ]] doc.add_entry("example4", "gallery4", { name="Gallery with 4 images", data = { {image="default_dirt.png"}, {image="default_leaves.png"}, {image="default_brick.png"}, {image="default_gold_block.png"} }, }) doc.add_entry("example4", "gallery5", { name="Gallery with 5 images", data = { {image="default_dirt.png"}, {image="default_leaves.png"}, {image="default_brick.png"}, {image="default_gold_block.png"}, {image="default_bronze_block.png"} }, }) doc.add_entry("example4", "gallery6", { name="Gallery with 6 images", data = { {image="default_grass.png"}, {image="default_dirt.png"}, {image="default_leaves.png"}, {image="default_brick.png"}, {image="default_gold_block.png"}, {image="default_bronze_block.png"}}, }) doc.add_entry("example4", "gallery7", { name="Gallery with 7 item images", data = { -- You can use this syntax to display item images instead of normal textures {image="default:bookshelf", imagetype="item"}, {image="default:grass_5", imagetype="item"}, {image="default:dirt", imagetype="item"}, {image="default:fence_wood", imagetype="item"}, {image="default:flint", imagetype="item"}, {image="default:goldblock", imagetype="item"}, {image="default:bronzeblock", imagetype="item"}}, })