diff --git a/_en/basics/getting_started.md b/_en/basics/getting_started.md
index 540e084..731acfd 100644
--- a/_en/basics/getting_started.md
+++ b/_en/basics/getting_started.md
@@ -24,7 +24,7 @@ creating mods.
## What are Games and Mods?
The power of Minetest is the ability to easily develop games without the need
-to create your own voxel graphics, voxel algorithms or fancy networking code.
+to create your own voxel graphics, voxel algorithms, or fancy networking code.
In Minetest, a game is a collection of modules which work together to provide the
content and behaviour of a game.
diff --git a/_en/games/games.md b/_en/games/games.md
index a8e1369..b005809 100644
--- a/_en/games/games.md
+++ b/_en/games/games.md
@@ -7,8 +7,8 @@ idx: 6.1
## Introduction
-The power of Minetest is the ability to easily create games without the need
-to write your own voxel graphics and algorithms or fancy networking.
+The power of Minetest is the ability to easily develop games without the need
+to create your own voxel graphics, voxel algorithms, or fancy networking code.
* [What is a Game?](#what-is-a-game)
* [Game Directory](#game-directory)
@@ -21,8 +21,8 @@ to write your own voxel graphics and algorithms or fancy networking.
Games are a collection of mods which work together to make a cohesive game.
A good game has a consistent underlying theme and a direction, for example
-maybe it's a classic crafter miner with hard survival elements, or maybe
-it's a space simulation game with a steam punk automation ascetic.
+it could be a classic crafter miner with hard survival elements, or
+it could be a space simulation game with a steam punk automation aesthetic.
Game design is a complex topic, and is actually a whole field of expertise.
It's beyond the scope of the book to more than briefly touch on it.
@@ -31,7 +31,7 @@ It's beyond the scope of the book to more than briefly touch on it.
The structure and location of a game will seem rather familiar after working
with mods.
-Games are found in a game location such as `minetest/games/ A player name is passed instead of a player object, because mods
+ message: A player name is passed instead of a player object because mods
can run commands on behalf of offline players. For example, the IRC
bridge allows players to run commands without joining the game. So make sure that you don't assume that the player is online.
- You can check by seeing if minetest.get_player_by_name returns a player.minetest.get_player_by_name
returns a player.
There is also a library written by the author of this book which can be used -to make complex chat commands without Patterns called -[ChatCmdBuilder](chat_complex.html). +to make complex chat commands without patterns called +Chat Command Builder. +
## Intercepting Messages @@ -155,8 +142,8 @@ end) ``` By returning false, you allow the chat message to be sent by the default -handler. You can actually remove the line `return false`, and it would still -work the same. +handler. You can actually remove the line `return false` and it would still +work the same, because `nil` is returned implicitly and is treated like false. {% include notice.html notice=page.cb_cmdsprivs %} diff --git a/_en/players/hud.md b/_en/players/hud.md index 203f243..ae24b1d 100644 --- a/_en/players/hud.md +++ b/_en/players/hud.md @@ -10,7 +10,7 @@ redirect_from: /en/chapters/hud.html Heads Up Display (HUD) elements allow you to show text, images, and other graphical elements. -The HUD doesn't accept user input. For that, you should use a [Formspec](formspecs.html). +The HUD doesn't accept user input; for that, you should use a [formspec](formspecs.html). * [Positioning](#positioning) * [Position and Offset](#position-and-offset) @@ -43,8 +43,8 @@ the HUD needs to work well on all screen types. Minetest's solution to this is to specify the location of an element using both a percentage position and an offset. The percentage position is relative to the screen size, so to place an element -in the center of the screen you would need to provide a percentage position of half -the screen, eg (50%, 50%), and an offset of (0, 0). +in the centre of the screen, you would need to provide a percentage position of half +the screen, e.g. (50%, 50%), and an offset of (0, 0). The offset is then used to move an element relative to the percentage position. @@ -55,7 +55,7 @@ The offset is then used to move an element relative to the percentage position. Alignment is where the result of position and offset is on the element - for example, `{x = -1.0, y = 0.0}` will make the result of position and offset point to the left of the element's bounds. This is particularly useful when you want to -make a text element left, center, or right justified. +make a text element aligned to the left, centre, or right. -In the above screenshot all the elements have the same percentage position - +In the above screenshot, all the elements have the same percentage position (100%, 50%) - but different offsets. This allows the whole thing to be anchored to the right of the window, but to resize without breaking. @@ -107,16 +107,21 @@ or remove a HUD element. The element's type is given using the `hud_elem_type` property in the definition table. The meaning of other properties varies based on this type. -`scale` is the maximum bounds of text, text outside these bounds is cropped, eg: `{x=100, y=100}`. +`scale` is the maximum bounds of text; text outside these bounds is cropped, e.g.: `{x=100, y=100}`. -`number` is the text's colour, and is in [Hexadecimal form](http://www.colorpicker.com/), eg: `0xFF0000`. +`number` is the text's colour, and is in [hexadecimal form](http://www.colorpicker.com/), e.g.: `0xFF0000`. ### Our Example -Let's go ahead, and place all the text in our score panel: +Let's go ahead and place all the text in our score panel: ```lua +-- Get the dig and place count from storage, or default to 0 +local meta = player:get_meta() +local digs_text = "Digs: " .. meta:get_int("score:digs") +local places_text = "Places: " .. meta:get_int("score:places") + player:hud_add({ hud_elem_type = "text", position = {x = 1, y = 0.5}, @@ -127,12 +132,6 @@ player:hud_add({ number = 0xFFFFFF, }) --- Get the dig and place count from storage, or default to 0 -local digs = tonumber(player:get_attribute("score:digs") or 0) -local digs_text = "Digs: " .. digs -local places = tonumber(player:get_attribute("score:digs") or 0) -local places_text = "Places: " .. places - player:hud_add({ hud_elem_type = "text", position = {x = 1, y = 0.5}, @@ -191,8 +190,8 @@ You will now have this: The `text` field is used to provide the image name. If a co-ordinate is positive, then it is a scale factor with 1 being the -original image size, and 2 being double the size, and so on. -However, if a co-ordinate is negative it is a percentage of the screensize. +original image size, 2 being double the size, and so on. +However, if a co-ordinate is negative, it is a percentage of the screensize. For example, `x=-100` is 100% of the width. ### Scale @@ -200,7 +199,7 @@ For example, `x=-100` is 100% of the width. Let's make the progress bar for our score panel as an example of scale: ```lua -local percent = tonumber(player:get_attribute("score:score") or 0.2) +local percent = tonumber(meta:get("score:score") or 0.2) player:hud_add({ hud_elem_type = "image", @@ -226,7 +225,7 @@ There is one problem however, it won't update when the stats change. ## Changing an Element -You can use the ID returned by the hud_add method to update or remove it later. +You can use the ID returned by the hud_add method to update it or remove it later. ```lua local idx = player:hud_add({ @@ -261,12 +260,11 @@ local saved_huds = {} function score.update_hud(player) local player_name = player:get_player_name() - local digs = tonumber(player:get_attribute("score:digs") or 0) - local digs_text = "Digs: " .. digs - local places = tonumber(player:get_attribute("score:digs") or 0) - local places_text = "Places: " .. places - - local percent = tonumber(player:get_attribute("score:score") or 0.2) + -- Get the dig and place count from storage, or default to 0 + local meta = player:get_meta() + local digs_text = "Digs: " .. meta:get_int("score:digs") + local places_text = "Places: " .. meta:get_int("score:places") + local percent = tonumber(meta:get("score:score") or 0.2) local ids = saved_huds[player_name] if ids then diff --git a/_en/players/player_physics.md b/_en/players/player_physics.md index 0ed62f4..5ea8e8a 100644 --- a/_en/players/player_physics.md +++ b/_en/players/player_physics.md @@ -8,14 +8,16 @@ redirect_from: /en/chapters/player_physics.html ## Introduction -Player physics can be modified using physics overrides. Physics overrides can set the -walking speed, jump speed and gravity constants. Physics overrides are set on a player -by player basis, and are multipliers. For example, a value of 2 for gravity would make -gravity twice as strong. +Player physics can be modified using physics overrides. +Physics overrides can set the walking speed, jump speed, +and gravity constants. +Physics overrides are set on a player-by-player basis, +and are multipliers. +For example, a value of 2 for gravity would make gravity twice as strong. * [Basic Example](#basic_example) * [Available Overrides](#available_overrides) -* [Mod Incompatibility ](#mod_incompatibility) +* [Mod Incompatibility](#mod_incompatibility) * [Your Turn](#your_turn) ## Basic Example @@ -28,16 +30,16 @@ minetest.register_chatcommand("antigravity", { func = function(name, param) local player = minetest.get_player_by_name(name) player:set_physics_override({ - gravity = 0.1 -- set gravity to 10% of its original value - -- (0.1 * 9.81) + gravity = 0.1, -- set gravity to 10% of its original value + -- (0.1 * 9.81) }) - end + end, }) ``` ## Available Overrides -player:set_physics_override() is given a table of overrides.\\ +`player:set_physics_override()` is given a table of overrides.\\ According to [lua_api.txt]({{ page.root }}/lua_api.html#player-only-no-op-for-other-objects), these can be: @@ -57,7 +59,7 @@ unintended, it has been preserved in overrides due to its use on many servers. Two overrides are needed to fully restore old movement behaviour: * new_move: whether the player uses new movement (default: true) -* sneak_glitch: whether the player can use "sneak elevators" (default: false) +* sneak_glitch: whether the player can use 'sneak elevators' (default: false) ## Mod Incompatibility @@ -69,5 +71,5 @@ player's speed, only the last one to run will be in effect. ## Your Turn * **Sonic**: Set the speed multiplier to a high value (at least 6) when a player joins the game. -* **Super bounce**: Increase the jump value so that the player can jump 20 meters (1 meter is 1 node). +* **Super bounce**: Increase the jump value so that the player can jump 20 metres (1 metre is 1 node). * **Space**: Make gravity decrease as the player gets higher. diff --git a/_en/players/sfinv.md b/_en/players/sfinv.md index 4a9e690..f24e539 100644 --- a/_en/players/sfinv.md +++ b/_en/players/sfinv.md @@ -12,10 +12,10 @@ Simple Fast Inventory (SFINV) is a mod found in Minetest Game that is used to create the player's inventory [formspec](formspecs.html). SFINV comes with an API that allows you to add and otherwise manage the pages shown. -Whilst SFINV by default shows pages as tabs, pages are called "pages" as -it's entirely possible that a mod or game decides to show them in +Whilst SFINV by default shows pages as tabs, pages are called pages +because it is entirely possible that a mod or game decides to show them in some other format instead. -For example, multiple pages could be shown on one view. +For example, multiple pages could be shown in one formspec. * [Registering a Page](#registering-a-page) * [Receiving events](#receiving-events) @@ -25,7 +25,7 @@ For example, multiple pages could be shown on one view. ## Registering a Page SFINV provides the aptly named `sfinv.register_page` function to create pages. -Simply call the function with the page's name, and its definition: +Simply call the function with the page's name and its definition: ```lua sfinv.register_page("mymod:hello", { @@ -41,7 +41,7 @@ The `make_formspec` function surrounds your formspec with SFINV's formspec code. The fourth parameter, currently set as `true`, determines whether the player's inventory is shown. -Let's make things more exciting. Here is the code for the formspec generation +Let's make things more exciting; here is the code for the formspec generation part of a player admin tab. This tab will allow admins to kick or ban players by selecting them in a list and clicking a button. @@ -83,14 +83,11 @@ sfinv.register_page("myadmin:myadmin", { }) ``` -There's nothing new about the above code, all the concepts are covered above and -in previous chapters. +There's nothing new about the above code; all the concepts are +covered above and in previous chapters. ## Receiving events @@ -104,10 +101,10 @@ on_player_receive_fields = function(self, player, context, fields) end, ``` -Fields is the exact same as the fields given to the subscribers of -`minetest.register_on_player_receive_fields`. The return value of -`on_player_receive_fields` is the same as a normal player receive fields. -Please note that sfinv will consume events relevant to itself, such as +`on_player_receive_fields` works the same as +`minetest.register_on_player_receive_fields`, except that `context` is +given instead of `formname`. +Please note that SFINV will consume events relevant to itself, such as navigation tab events, so you won't receive them in this callback. Now let's implement the `on_player_receive_fields` for our admin mod: @@ -166,7 +163,7 @@ If you only need to check one priv or want to perform an 'and', you should use Note that the `is_in_nav` is only called when the player's inventory formspec is generated. This happens when a player joins the game, switches tabs, or a mod -requests it using SFINV's API. +requests for SFINV to regenerate. This means that you need to manually request that SFINV regenerates the inventory formspec on any events that may change `is_in_nav`'s result. In our case, diff --git a/_en/quality/clean_arch.md b/_en/quality/clean_arch.md index c9eccd5..f167938 100644 --- a/_en/quality/clean_arch.md +++ b/_en/quality/clean_arch.md @@ -33,7 +33,7 @@ code is thrown in together with no clear boundaries. This ultimately makes a project completely unmaintainable, ending in its abandonment. The opposite of this is to design your project as a collection of interacting -smaller programs or areas of code. +smaller programs or areas of code. > Inside every large program, there is a small program trying to get out. > @@ -51,14 +51,13 @@ a low amount of coupling, as this means that changing the APIs of certain areas will be more feasible. Note that these apply both when thinking about the relationship between mods, -and the relationship between areas inside a mod. In both cases you should try -to get high cohesion and low coupling. +and the relationship between areas inside a mod. ## Model-View-Controller -In the next chapter we will discuss how to automatically test your code, and one -of the problems we will have is how to separate your logic +In the next chapter, we will discuss how to automatically test your +code and one of the problems we will have is how to separate your logic (calculations, what should be done) from API calls (`minetest.*`, other mods) as much as possible. @@ -75,7 +74,7 @@ and any associated metadata. Actions you can take are `create`, `edit`, or receive fields. These are 3 areas that can usually be separated pretty well. In your tests, you will be able to make sure that an action when triggered does -the right thing to the data, but you won't need to test that an event calls an +the right thing to the data. You won't need to test that an event calls an action (as this would require using the Minetest API, and this area of code should be made as small as possible anyway.) @@ -98,8 +97,8 @@ function land.get_by_name(area_name) end ``` -Your actions should also be pure, however calling other functions is more -acceptable. +Your actions should also be pure, but calling other functions is more +acceptable than in the above. ```lua -- Controller @@ -155,7 +154,7 @@ most of the calculations are made. The controller should have no knowledge about the Minetest API - notice how there are no Minetest calls or any view functions that resemble them. You should *NOT* have a function like `view.hud_add(player, def)`. -Instead, the view defines some actions the controller can tell the view to do, +Instead, the view defines some actions that the controller can tell the view to do, like `view.add_hud(info)` where info is a value or table which doesn't relate to the Minetest API at all. @@ -167,27 +166,27 @@ to the Minetest API at all. It is important that each area only communicates with its direct neighbours, -as shown above, in order to reduce how much you needs to change if you modify +as shown above, in order to reduce how much you need to change if you modify an area's internals or externals. For example, to change the formspec you would only need to edit the view. To change the view API, you would only need to change the view and the controller, but not the model at all. In practice, this design is rarely used because of the increased complexity and because it doesn't give many benefits for most types of mods. Instead, -you tend to see a lot more of a less formal and strict kind of design - -varients of the API-View. +you will commonly see a less formal and strict kind of design - +variants of the API-View. ### API-View In an ideal world, you'd have the above 3 areas perfectly separated with all events going into the controller before going back to the normal view. But -this isn't the real world. A good half-way house is to reduce the mod into 2 +this isn't the real world. A good compromise is to reduce the mod into two parts: -* **API** - what was the model and controller. There should be no uses of +* **API** - This was the model and controller above. There should be no uses of `minetest.` here. -* **View** - the view as before. It's a good idea to structure this into separate +* **View** - This was also the view above. It's a good idea to structure this into separate files for each type of event. rubenwardy's [crafting mod](https://github.com/rubenwardy/crafting) roughly @@ -204,40 +203,38 @@ as it doesn't use any Minetest APIs - as shown in the ## Observer Reducing coupling may seem hard to do to begin with, but you'll make a lot of -progress by splitting your code up well using a design like the one given above. +progress by splitting your code up using a design like the one given above. It's not always possible to remove the need for one area to communicate with -another, but there are ways to decouple anyway - one such way being the Observer +another, but there are ways to decouple anyway - one example being the Observer pattern. Let's take the example of unlocking an achievement when a player first kills a -rare animal. The naive approach would be to have achievement code in the mob +rare animal. The naïve approach would be to have achievement code in the mob kill function, checking the mob name and unlocking the award if it matches. This is a bad idea however, as it makes the mobs mod coupled to the achievements code. If you kept on doing this - for example, adding XP to the mob death code - you could end up with a lot of messy dependencies. -Enter the Observer pattern. Instead of the mobs mod caring about awards, mobs -exposes a way for other areas of code to register their interest in an event -and receive data about the event. +Enter the Observer pattern. Instead of the mymobs mod caring about awards, +the mymobs mod exposes a way for other areas of code to register their +interest in an event and receive data about the event. ```lua -mobs.registered_on_death = {} -function mobs.register_on_death(func) - table.insert(mobs.registered_on_death, func) +mymobs.registered_on_death = {} +function mymobs.register_on_death(func) + table.insert(mymobs.registered_on_death, func) end -- mob death code -for i=1, #mobs.registered_on_death do - mobs.registered_on_death[i](entity, reason) +for i=1, #mymobs.registered_on_death do + mymobs.registered_on_death[i](entity, reason) end ``` Then the other code registers its interest: ```lua - --- awards -mobs.register_on_death(function(mob, reason) +mymobs.register_on_death(function(mob, reason) if reason.type == "punch" and reason.object and reason.object:is_player() then awards.notify_mob_kill(reason.object, mob.name) @@ -246,12 +243,12 @@ end) ``` You may be thinking - wait a second, this looks awfully familiar. And you're right! -The Minetest API is heavily Observer based to stop the engine having to care about +The Minetest API is heavily Observer-based to stop the engine having to care about what is listening to something. ## Conclusion -Good code design is subjective, and depends on the project you're making. As a +Good code design is subjective, and highly depends on the project you're making. As a general rule, try to keep cohesion high and coupling low. Phrased differently, keep related code together and unrelated code apart, and keep dependencies simple. diff --git a/_en/quality/common_mistakes.md b/_en/quality/common_mistakes.md index 12eb98a..c1360ba 100644 --- a/_en/quality/common_mistakes.md +++ b/_en/quality/common_mistakes.md @@ -40,7 +40,7 @@ minetest.register_on_joinplayer(function(player) end) ``` -Do this: +Do this instead: ```lua minetest.register_on_joinplayer(function(player) @@ -62,10 +62,10 @@ end) ## Don't Trust Formspec Submissions -Malicious clients can submit formspecs whenever they like with whatever content -they like. +Malicious clients can submit formspecs whenever they like, with +whatever content they like. -For example, the following code has a vulnerability which will allow players to +For example, the following code has a vulnerability which allows players to give themselves moderator privileges: ```lua @@ -123,7 +123,7 @@ stack:get_meta():set_string("description", "Partially eaten") -- BAD! Modification will be lost ``` -Do this: +Do this instead: ```lua local inv = player:get_inventory() @@ -137,8 +137,6 @@ The behaviour of callbacks is slightly more complicated. Modifying an `ItemStack are given will change it for the caller too, and any subsequent callbacks. However, it will only be saved in the engine if the callback caller sets it. -Avoid this: - ```lua minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing) @@ -149,7 +147,7 @@ end) ``` If no callbacks cancel this, the stack will be set and the description will be updated, -but if a callback cancels this, then the update may be lost. +but if a callback does cancel this, then the update may be lost. It's better to do this instead: diff --git a/_en/quality/luacheck.md b/_en/quality/luacheck.md index dfdeba8..ed46786 100644 --- a/_en/quality/luacheck.md +++ b/_en/quality/luacheck.md @@ -88,10 +88,10 @@ a look at the list below. ### Troubleshooting * **accessing undefined variable foobar** - If `foobar` is meant to be a global, - then add it to `read_globals`. Otherwise, add any missing `local`s to the mod. + add it to `read_globals`. Otherwise, add any missing `local`s to the mod. * **setting non-standard global variable foobar** - If `foobar` is meant to be a global, - then add it to `globals`. Remove from `read_globals` if present there. - Otherwise add any missing `local`s to the mod. + add it to `globals`. Remove from `read_globals` if present. + Otherwise, add any missing `local`s to the mod. * **mutating read-only global variable 'foobar'** - Move `foobar` from `read_globals` to `globals`. @@ -101,16 +101,16 @@ It is highly recommended that you find and install a plugin for your editor of c to show you errors without running a command. Most editors will likely have a plugin available. -* **Atom** - `linter-luacheck` +* **Atom** - `linter-luacheck`. * **Sublime** - Install using package-control: [SublimeLinter](https://github.com/SublimeLinter/SublimeLinter), - [SublimeLinter-luacheck](https://github.com/SublimeLinter/SublimeLinter-luacheck) + [SublimeLinter-luacheck](https://github.com/SublimeLinter/SublimeLinter-luacheck). ## Checking Commits with Travis If your project is public and is on Github, you can use TravisCI - a free service to run jobs on commits to check them. This means that every commit you push will -be checked against LuaCheck, and a green tick or red cross displayed next to them +be checked against LuaCheck, and a green tick or red cross will be displayed next to them depending on whether LuaCheck finds any mistakes. This is especially helpful for when your project receives a pull request - you'll be able to see the LuaCheck output without downloading the code. @@ -144,7 +144,7 @@ change the line after `script:` to: ``` Now commit and push to Github. Go to your project's page on Github, and click -commits. You should see an orange disc next to the commit you just made. +'commits'. You should see an orange disc next to the commit you just made. After a while it should change either into a green tick or a red cross depending on the outcome of LuaCheck. In either case, you can click the icon to see the build logs and the output of LuaCheck. diff --git a/_en/quality/releasing.md b/_en/quality/releasing.md index 3a0487a..7033df7 100644 --- a/_en/quality/releasing.md +++ b/_en/quality/releasing.md @@ -29,7 +29,7 @@ but can be suitable choices for artistic works such as images, text and meshes. You are allowed any license; however, mods which disallow derivatives are banned from the official Minetest forum. (For a mod to be allowed on the forum, other developers must be -able modify it and release the modified version.) +able to modify it and release the modified version.) Please note that **public domain is not a valid licence**, because the definition varies in different countries. @@ -37,17 +37,18 @@ in different countries. ### LGPL and CC-BY-SA This is a common license combination in the Minetest community, and is what -Minetest and minetest_game use. -You license your code under LGPL 2.1 and your art under CC-BY-SA. This means: +Minetest and Minetest Game use. +You license your code under LGPL 2.1 and your art under CC-BY-SA. +This means that: * Anyone can modify, redistribute and sell modified or unmodified versions. * If someone modifies your mod, they must give their version the same license. * Your copyright notice must be kept. -### WTFPL and CC0 +### CC0 -These licenses allows anyone to do what they want with your mod. -This means they can modify, redistribute, sell, or leave out attribution. +These licenses allow anyone to do what they want with your mod, +which means they can modify, redistribute, sell, or leave-out attribution. These licenses can be used for both code and art. It is important to note that WTFPL is strongly discouraged and people may @@ -61,19 +62,19 @@ in any copies of the mod or of substantial parts of the mod. ## Packaging -There are some files it is recommended to include in your mod -when you release it. +There are some files that are recommended to include in your mod +before you release it. ### README.txt -The readme file should state: +The README file should state: * What the mod does. * What the license is. -* Current version of mod. +* What dependencies there are. * How to install the mod. -* What dependencies there are / what the user needs to install. -* Where to report problems/bugs or get help. +* Current version of the mod. +* Optionally, the where to report problems or get help. ### description.txt @@ -85,7 +86,7 @@ Good example: Adds soup, cakes, bakes and juices. -Don't do this: +Avoid this: (BAD) The food mod for Minetest. @@ -133,10 +134,7 @@ your mods. This can be done when creating a mod's forum topic (covered below). You need to zip the files for the mod into a single file. How to do this varies from operating system to operating system. - -If you use Windows, go to the mod's folder and select all the files. -Right click, Send To > Compressed (zipped) folder. -Rename the resulting zip file to the name of your mod. +This is nearly always done using the right click menu after selecting all files. When making a forum topic, on the "Create a Topic" page (see below), go to the "Upload Attachment" tab at the bottom. @@ -155,24 +153,13 @@ enter the version of your mod in the comment field. You can now create a forum topic. You should create it in the ["WIP Mods"](https://forum.minetest.net/viewforum.php?f=9) (Work In Progress) forum.\\ -When you consider your mod no longer a work in progress, you can +When you no longer consider your mod a work in progress, you can [request that it be moved](https://forum.minetest.net/viewtopic.php?f=11&t=10418) to "Mod Releases." -### Content - -The requirements of a forum topic are mostly the same as the recommendations for -a readme file. The topic should include: - -* What the mod does. -* What the license is. -* Current version of mod. -* How to install the mod. -* What dependencies there are. -* Where to report problems/bugs or get help. -* Link to download, or an attachment. - -You should also include screenshots of your mod in action, if relevant. +The forum topic should contain similar content to the README, but should +be more promotional and also include a link to download the mod. +It's a good idea to include screenshots of your mod in action, if possible. The Minetest forum uses bbcode for formatting. Here is an example for a mod named superspecial: diff --git a/_en/quality/security.md b/_en/quality/security.md index 00fb738..88fafc0 100644 --- a/_en/quality/security.md +++ b/_en/quality/security.md @@ -20,12 +20,13 @@ owner to lose data or control. The most important concept in security is to **never trust the user**. Anything the user submits should be treated as malicious. -This means that you should always check that the user has the correct permissions, -that the give valid information, and they are otherwise allowed to do that action -(ie: in range or an owner) +This means that you should always check that the information they +enter is valid, that the user has the correct permissions, +and that they are otherwise allowed to do that action +(ie: in range or an owner). A malicious action isn't necessarily the modification or destruction of data, -but can be accessing data they're not supposed to such as password hashes or +but can be accessing sensitive data, such as password hashes or private messages. This is especially bad if the server stores information such as emails or ages, which some may do for verification purposes. @@ -59,8 +60,8 @@ This could even be automated using client modifications to essentially replicate the `/teleport` command with no need for a privilege. The solution for this kind of issue is to use a -[Context](../players/formspecs.html#contexts), as shown in -the formspecs chapter. +[Context](../players/formspecs.html#contexts), as shown previously in +the Formspecs chapter. ### Time of Check isn't Time of Use @@ -71,8 +72,8 @@ engine forbids it: * From 5.0 onward, named formspecs will be blocked if they haven't been shown yet. This means that you should check in the handler that the user meets the -conditions for showing the formspec in the first place, and any corresponding -actions. +conditions for showing the formspec in the first place, as well as any +corresponding actions. The vulnerability caused by checking for permissions in the show formspec but not in the handle formspec is called Time Of Check is not Time Of Use (TOCTOU). @@ -99,7 +100,7 @@ String.format = function() end ``` -The mod could pass something a lot more malicious than opening a website, such +The mod could pass something much more malicious than opening a website, such as giving a remote user control over the machine. Some rules for using an insecure environment: diff --git a/_en/quality/unit_testing.md b/_en/quality/unit_testing.md index a74960c..475fd7c 100644 --- a/_en/quality/unit_testing.md +++ b/_en/quality/unit_testing.md @@ -9,7 +9,7 @@ idx: 7.5 Unit tests are an essential tool in proving and reassuring yourself that your code is correct. This chapter will show you how to write tests for Minetest mods and -games using busted. Writing unit tests for functions where you call Minetest +games using Busted. Writing unit tests for functions where you call Minetest functions is quite difficult, but luckily [in the previous chapter](clean_arch.html) we discussed how to make your code avoid this. @@ -26,7 +26,7 @@ First you'll need to install LuaRocks. * Windows: Follow the [installation instructions on LuaRock's wiki](https://github.com/luarocks/luarocks/wiki/Installation-instructions-for-Windows). * Debian/Ubuntu Linux: `sudo apt install luarocks` -Next you should then install Busted globally: +Next you should install Busted globally: sudo luarocks install busted @@ -104,8 +104,8 @@ functions not inside of it. You tend to only write tests for a single file at on ## Mocking: Using External Functions Mocking is the practice of replacing functions that the thing you're testing depends -on. This can have two purposes - firstly, the function may not be available in the -test environment. Secondly, you may want to capture calls to the function and any +on. This can have two purposes; one, the function may not be available in the +test environment, and two, you may want to capture calls to the function and any passed arguments. If you follow the advice in the [Clean Architectures](clean_arch.html) chapter, @@ -163,7 +163,7 @@ end) ## Checking Commits with Travis -The Travis script from the [Error Checking](luacheck.html) +The Travis script from the [Automatic Error Checking](luacheck.html) chapter can be modified to also run Busted. ```yml