Replace tab character with four spaces for better formatting

master
rubenwardy 2017-08-26 19:01:51 +01:00
parent d68975ba9f
commit 5d64318342
18 changed files with 778 additions and 778 deletions

170
README.md
View File

@ -41,19 +41,19 @@ fit my idea of quality.
I use [Jekyll](http://jekyllrb.com/) 2.5.3
# For Linux based:
# For Linux based:
$ sudo apt-get install ruby-dev
$ gem install jekyll
$ gem install jekyll-sitemap
$ sudo apt-get install ruby-dev
$ gem install jekyll
$ gem install jekyll-sitemap
# You may need to use sudo on the above commands
# You may need to use sudo on the above commands
### Building as a website
You can build it as a website using [Jekyll](http://jekyllrb.com/)
$ jekyll build
$ jekyll build
Goes to _site/
@ -62,7 +62,7 @@ Goes to _site/
You can start a webserver on localhost which will automatically
rebuild pages when you modify their markdown source.
$ jekyll serve
$ jekyll serve
This serves at <http://localhost:4000> on my computer, but the port
@ -89,107 +89,107 @@ Replace spaces with underscores ( _ )
{% raw %}
---
title: Player Physics
layout: default
root: ../
---
---
title: Player Physics
layout: default
root: ../
---
Introduction
------------
Introduction
------------
Write an paragraph or so explaining what will be covered in this chapter.
Explain why/how these concepts are useful in modding
Write an paragraph or so explaining what will be covered in this chapter.
Explain why/how these concepts are useful in modding
* List the
* Parts in
* This chapter
* List the
* Parts in
* This chapter
Section
-------
Section
-------
Explaining the concept of something.
Explaining the concept of something.
You can link to other chapters like this: [chapter title]({{ relative }}/chaptertitle/).//
Do it like Wikipedia, link words in a sentence but avoid explicitly telling the user to view it//
or click the link.
You can link to other chapters like this: [chapter title]({{ relative }}/chaptertitle/).//
Do it like Wikipedia, link words in a sentence but avoid explicitly telling the user to view it//
or click the link.
Mod Name
- init.lua - the main scripting code file, which is run when the game loads.
- (optional) depends.txt - a list of mod names that needs to be loaded before this mod.
- (optional) textures/ - place images here, commonly in the format modname_itemname.png
- (optional) sounds/ - place sounds in here
- (optional) models/ - place 3d models in here
...and any other lua files to be included by init.lua
Mod Name
- init.lua - the main scripting code file, which is run when the game loads.
- (optional) depends.txt - a list of mod names that needs to be loaded before this mod.
- (optional) textures/ - place images here, commonly in the format modname_itemname.png
- (optional) sounds/ - place sounds in here
- (optional) models/ - place 3d models in here
...and any other lua files to be included by init.lua
Code snippets are tabbed one level in, except for lua snippets, which use a code highligter.
Code snippets are tabbed one level in, except for lua snippets, which use a code highligter.
Section 2
---------
Section 2
---------
Explaining another concept
Explaining another concept
{% highlight lua %}
print("This file will be run at load time!")
{% highlight lua %}
print("This file will be run at load time!")
minetest.register_node("mymod:node",{
description = "This is a node",
tiles = {
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png"
},
groups = {cracky = 1}
})
{% endhighlight %}
minetest.register_node("mymod:node",{
description = "This is a node",
tiles = {
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png"
},
groups = {cracky = 1}
})
{% endhighlight %}
Use the highlight tags to highlight Lua code.
Use the highlight tags to highlight Lua code.
Section 3
---------
Section 3
---------
You should include plenty of examples. Each example should
be able to be installed in a mod and used. Don't do the thing where
you make the reading create the mod line-by-line, it is rather annoying
and good code can explain itself. Explaining line-by-line is needed in earlier chapters,
and when introducing new concepts.
You should include plenty of examples. Each example should
be able to be installed in a mod and used. Don't do the thing where
you make the reading create the mod line-by-line, it is rather annoying
and good code can explain itself. Explaining line-by-line is needed in earlier chapters,
and when introducing new concepts.
### Mod Folder
mymod/
- init.lua
- depends.txt
### Mod Folder
mymod/
- init.lua
- depends.txt
default
default
{% highlight lua %}
print("This file will be run at load time!")
{% highlight lua %}
print("This file will be run at load time!")
minetest.register_node("mymod:node",{
description = "This is a node",
tiles = {
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png"
},
groups = {cracky = 1}
})
{% endhighlight %}
minetest.register_node("mymod:node",{
description = "This is a node",
tiles = {
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png"
},
groups = {cracky = 1}
})
{% endhighlight %}
Explain the code here, but there is no need to explain every single line.
Use comments and indentation well.
Explain the code here, but there is no need to explain every single line.
Use comments and indentation well.
Your Turn
---------
Your Turn
---------
* **Set Tasks:** Make tasks for the reader to do.
* **Start easy, get hard:** Start with easier ones, and work up to harder ones.
* **Set Tasks:** Make tasks for the reader to do.
* **Start easy, get hard:** Start with easier ones, and work up to harder ones.
{% endraw %}

View File

@ -23,21 +23,21 @@ blocks.
{% highlight lua %}
minetest.register_node("aliens:grass", {
description = "Alien Grass",
light_source = 3, -- The node radiates light. Values can be from 1 to 15
tiles = {"aliens_grass.png"},
groups = {choppy=1},
on_use = minetest.item_eat(20)
description = "Alien Grass",
light_source = 3, -- The node radiates light. Values can be from 1 to 15
tiles = {"aliens_grass.png"},
groups = {choppy=1},
on_use = minetest.item_eat(20)
})
minetest.register_abm({
nodenames = {"default:dirt_with_grass"},
neighbors = {"default:water_source", "default:water_flowing"},
interval = 10.0, -- Run every 10 seconds
chance = 50, -- Select every 1 in 50 nodes
action = function(pos, node, active_object_count, active_object_count_wider)
minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "aliens:grass"})
end
nodenames = {"default:dirt_with_grass"},
neighbors = {"default:water_source", "default:water_flowing"},
interval = 10.0, -- Run every 10 seconds
chance = 50, -- Select every 1 in 50 nodes
action = function(pos, node, active_object_count, active_object_count_wider)
minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "aliens:grass"})
end
})
{% endhighlight %}

View File

@ -26,9 +26,9 @@ minetest.chat_send_all("This is a chat message to all players")
Here is an example of how it would appear ingame (there are other messages
around it).
<player1> Look at this entrance
This is a chat message to all players
<player2> What about it?
<player1> Look at this entrance
This is a chat message to all players
<player2> What about it?
## Send a message to a certain player
@ -59,12 +59,12 @@ In order to register a chat command, such as /foo, use register_chatcommand:
{% highlight lua %}
minetest.register_chatcommand("foo", {
privs = {
interact = true
},
func = function(name, param)
return true, "You said " .. param .. "!"
end
privs = {
interact = true
},
func = function(name, param)
return true, "You said " .. param .. "!"
end
})
{% endhighlight %}
@ -74,7 +74,7 @@ Let's do a break down:
{% highlight lua %}
privs = {
interact = true
interact = true
},
{% endhighlight %}
@ -116,8 +116,8 @@ You can use register_on_chat_message, like so:
{% highlight lua %}
minetest.register_on_chat_message(function(name, message)
print(name .. " said " .. message)
return false
print(name .. " said " .. message)
return false
end)
{% endhighlight %}
@ -130,12 +130,12 @@ player messages, you need to do this:
{% highlight lua %}
minetest.register_on_chat_message(function(name, message)
if message:sub(1, 1) == "/" then
print(name .. " ran chat command")
return false
end
if message:sub(1, 1) == "/" then
print(name .. " ran chat command")
return false
end
print(name .. " said " .. message)
return false
print(name .. " said " .. message)
return false
end)
{% endhighlight %}

View File

@ -28,21 +28,21 @@ Because of this, I created a library to do this for you.
{% highlight lua %}
ChatCmdBuilder.new("sethp", function(cmd)
cmd:sub(":target :hp:int", function(name, target, hp)
local player = minetest.get_player_by_name(target)
if player then
player:set_hp(hp)
return true, "Killed " .. target
else
return false, "Unable to find " .. target
end
end)
cmd:sub(":target :hp:int", function(name, target, hp)
local player = minetest.get_player_by_name(target)
if player then
player:set_hp(hp)
return true, "Killed " .. target
else
return false, "Unable to find " .. target
end
end)
end, {
description = "Set hp of player",
privs = {
kick = true
-- ^ probably better to register a custom priv
}
description = "Set hp of player",
privs = {
kick = true
-- ^ probably better to register a custom priv
}
})
{% endhighlight %}
@ -94,7 +94,7 @@ function in order.
{% highlight lua %}
cmd:sub(":target :hp:int", function(name, target, hp)
-- subcommand function
-- subcommand function
end)
{% endhighlight %}
@ -118,55 +118,55 @@ Here is an example that creates a chat command that allows us to do this:
{% highlight lua %}
local admin_log
local function load()
admin_log = {}
admin_log = {}
end
local function save()
-- todo
-- todo
end
load()
ChatCmdBuilder.new("admin", function(cmd)
cmd:sub("kill :name", function(name, target)
local player = minetest.get_player_by_name(target)
if player then
player:set_hp(0)
return true, "Killed " .. target
else
return false, "Unable to find " .. target
end
end)
cmd:sub("kill :name", function(name, target)
local player = minetest.get_player_by_name(target)
if player then
player:set_hp(0)
return true, "Killed " .. target
else
return false, "Unable to find " .. target
end
end)
cmd:sub("move :name to :pos:pos", function(name, target, pos)
local player = minetest.get_player_by_name(target)
if player then
player:setpos(pos)
return true, "Moved " .. target .. " to " .. minetest.pos_to_string(pos)
else
return false, "Unable to find " .. target
end
end)
cmd:sub("move :name to :pos:pos", function(name, target, pos)
local player = minetest.get_player_by_name(target)
if player then
player:setpos(pos)
return true, "Moved " .. target .. " to " .. minetest.pos_to_string(pos)
else
return false, "Unable to find " .. target
end
end)
cmd:sub("log :username", function(name, target)
local log = admin_log[target]
if log then
return true, table.concat(log, "\n")
else
return false, "No entries for " .. target
end
end)
cmd:sub("log :username", function(name, target)
local log = admin_log[target]
if log then
return true, table.concat(log, "\n")
else
return false, "No entries for " .. target
end
end)
cmd:sub("log :username :message", function(name, target, message)
local log = admin_log[target] or {}
table.insert(log, message)
admin_log[target] = log
save()
return true, "Logged"
end)
cmd:sub("log :username :message", function(name, target, message)
local log = admin_log[target] or {}
table.insert(log, message)
admin_log[target] = log
save()
return true, "Logged"
end)
end, {
description = "Admin tools",
privs = {
kick = true,
ban = true
}
description = "Admin tools",
privs = {
kick = true,
ban = true
}
})
{% endhighlight %}

View File

@ -31,19 +31,19 @@ learning curve as lots of its features are hidden away.
### Use the pencil tool to edit individual pixels
<figure>
<img src="{{ page.root }}/static/pixel_art_gimp_pencil.png" alt="Pencil in GIMP">
<figcaption>
Pencil in GIMP
</figcaption>
<img src="{{ page.root }}/static/pixel_art_gimp_pencil.png" alt="Pencil in GIMP">
<figcaption>
Pencil in GIMP
</figcaption>
</figure>
### Set the rubber to hard edge
<figure>
<img src="{{ page.root }}/static/pixel_art_gimp_rubber.png" alt="Rubber in GIMP">
<figcaption>
Rubber in GIMP
</figcaption>
<img src="{{ page.root }}/static/pixel_art_gimp_rubber.png" alt="Rubber in GIMP">
<figcaption>
Rubber in GIMP
</figcaption>
</figure>
## Common Mistakes

View File

@ -27,13 +27,13 @@ Mod names can be made up of letters, numbers, or underscores. The folder a mod i
in needs to be called the same as the mod name.
### Mod Folder Structure
Mod name (eg: "mymod")
- init.lua - the main scripting code file, which is run when the game loads.
- (optional) depends.txt - a list of mod names that needs to be loaded before this mod.
- (optional) textures/ - place images here, commonly in the format modname_itemname.png
- (optional) sounds/ - place sounds in here
- (optional) models/ - place 3d models in here
...and any other lua files to be included by init.lua
Mod name (eg: "mymod")
- init.lua - the main scripting code file, which is run when the game loads.
- (optional) depends.txt - a list of mod names that needs to be loaded before this mod.
- (optional) textures/ - place images here, commonly in the format modname_itemname.png
- (optional) sounds/ - place sounds in here
- (optional) models/ - place 3d models in here
...and any other lua files to be included by init.lua
Only the init.lua file is required in a mod for it to run on game load; however,
the other items are needed by some mods to perform their functionality.
@ -45,9 +45,9 @@ needs to be loaded before this mod.
**depends.txt**
modone
modtwo
modthree?
modone
modtwo
modthree?
As you can see, each modname is on its own line.
@ -64,43 +64,43 @@ They are useful if you want to supply multiple mods to a player but don't
want to make them download each one individually.
### Mod Pack Folder Structure
modpackfolder/
- modone/
- modtwo/
- modthree/
- modfour/
- modpack.txt signals that this is a mod pack, content does not matter
modpackfolder/
- modone/
- modtwo/
- modthree/
- modfour/
- modpack.txt signals that this is a mod pack, content does not matter
## Example Time
Are you confused? Don't worry, here is an example putting all of this together.
### Mod Folder
mymod/
- textures/
- - mymod_node.png
- init.lua
- depends.txt
mymod/
- textures/
- - mymod_node.png
- init.lua
- depends.txt
### depends.txt
default
default
### init.lua
{% highlight lua %}
print("This file will be run at load time!")
minetest.register_node("mymod:node", {
description = "This is a node",
tiles = {
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png"
},
groups = {cracky = 1}
description = "This is a node",
tiles = {
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png",
"mymod_node.png"
},
groups = {cracky = 1}
})
{% endhighlight %}

View File

@ -7,10 +7,10 @@ root: ../../
## Introduction
<figure class="right_image">
<img src="{{ page.root }}/static/formspec_example.png" alt="Furnace Inventory">
<figcaption>
Screenshot of furnace formspec, labelled.
</figcaption>
<img src="{{ page.root }}/static/formspec_example.png" alt="Furnace Inventory">
<figcaption>
Screenshot of furnace formspec, labelled.
</figcaption>
</figure>
In this chapter we will learn how to create a formspec and display it to the user.
@ -32,7 +32,7 @@ tend to disrupt game play.
Formspecs have a rather weird syntax.
They consist of a series of tags which are in the following form:
element_type[param1;param2;...]
element_type[param1;param2;...]
Firstly the element type is declared, and then the attributes are given
in square brackets.
@ -42,7 +42,7 @@ as size or background).
Here are two elements, of types foo and bar.
foo[param1]bar[param1]
foo[param1]bar[param1]
### Size[w, h]
@ -53,7 +53,7 @@ The reason this is used is because it is independent on screen resolution -
The form should work just as well on large screens as small screens.
You can use decimals in sizes and co-ordinates.
size[5,2]
size[5,2]
Co-ordinates and sizes only use one attribute.
The x and y values are separated by a comma, as you can see above.
@ -64,7 +64,7 @@ This is a textbox element. Most other elements have a similar style of attribute
The "name" attribute is used in callbacks to get the submitted information.
The others are pretty self-explaintary.
field[1,1;3,1;firstname;Firstname;]
field[1,1;3,1;firstname;Firstname;]
It is perfectly valid to not define an attribute, like above.
@ -78,7 +78,7 @@ It is near line 1019, at time of writing.
Here is a generalized way to show a formspec
minetest.show_formspec(playername, formname, formspec)
minetest.show_formspec(playername, formname, formspec)
Formnames should be itemnames, however that is not enforced.
There is no need to override a formspec here, formspecs are not registered like
@ -90,23 +90,23 @@ and see if the callback is relevant.
### Example
<figure class="right_image">
<img src="{{ page.root }}/static/formspec_name.png" alt="Name Formspec">
<figcaption>
The formspec generated by<br />
the example's code
</figcaption>
<img src="{{ page.root }}/static/formspec_name.png" alt="Name Formspec">
<figcaption>
The formspec generated by<br />
the example's code
</figcaption>
</figure>
{% highlight lua %}
-- Show form when the /formspec command is used.
minetest.register_chatcommand("formspec", {
func = function(name, param)
minetest.show_formspec(name, "mymod:form",
"size[4,3]" ..
"label[0,0;Hello, " .. name .. "]" ..
"field[1,1.5;3,1;name;Name;]" ..
"button_exit[1,2;2,1;exit;Save]")
end
func = function(name, param)
minetest.show_formspec(name, "mymod:form",
"size[4,3]" ..
"label[0,0;Hello, " .. name .. "]" ..
"field[1,1.5;3,1;name;Name;]" ..
"button_exit[1,2;2,1;exit;Save]")
end
})
{% endhighlight %}
@ -126,29 +126,29 @@ Let's expand on the above example.
{% highlight lua %}
-- Show form when the /formspec command is used.
minetest.register_chatcommand("formspec", {
func = function(name, param)
minetest.show_formspec(name, "mymod:form",
"size[4,3]" ..
"label[0,0;Hello, " .. name .. "]" ..
"field[1,1.5;3,1;name;Name;]" ..
"button_exit[1,2;2,1;exit;Save]")
end
func = function(name, param)
minetest.show_formspec(name, "mymod:form",
"size[4,3]" ..
"label[0,0;Hello, " .. name .. "]" ..
"field[1,1.5;3,1;name;Name;]" ..
"button_exit[1,2;2,1;exit;Save]")
end
})
-- Register callback
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "mymod:form" then
-- Formname is not mymod:form,
-- exit callback.
return false
end
if formname ~= "mymod:form" then
-- Formname is not mymod:form,
-- exit callback.
return false
end
-- Send message to player.
minetest.chat_send_player(player:get_player_name(), "You said: " .. fields.name .. "!")
-- Send message to player.
minetest.chat_send_player(player:get_player_name(), "You said: " .. fields.name .. "!")
-- Return true to stop other minetest.register_on_player_receive_fields
-- from receiving this submission.
return true
-- Return true to stop other minetest.register_on_player_receive_fields
-- from receiving this submission.
return true
end)
{% endhighlight %}
@ -176,8 +176,8 @@ for a clicked button.
-- An example of what fields could contain,
-- using the above code
{
name = "Foo Bar",
exit = true
name = "Foo Bar",
exit = true
}
{% endhighlight %}
@ -198,21 +198,21 @@ Let's say you are making a form to handle land protection information.
local land_formspec_context = {}
minetest.register_chatcommand("land", {
func = function(name, param)
if param == "" then
minetest.chat_send_player(name, "Incorrect parameters - supply a land ID")
return
end
func = function(name, param)
if param == "" then
minetest.chat_send_player(name, "Incorrect parameters - supply a land ID")
return
end
-- Save information
land_formspec_context[name] = {id = param}
-- Save information
land_formspec_context[name] = {id = param}
minetest.show_formspec(name, "mylandowner:edit",
"size[4,4]" ..
"field[1,1;3,1;plot;Plot Name;]" ..
"field[1,2;3,1;owner;Owner;]" ..
"button_exit[1,3;2,1;exit;Save]")
end
minetest.show_formspec(name, "mylandowner:edit",
"size[4,4]" ..
"field[1,1;3,1;plot;Plot Name;]" ..
"field[1,2;3,1;owner;Owner;]" ..
"button_exit[1,3;2,1;exit;Save]")
end
})
@ -221,25 +221,25 @@ minetest.register_chatcommand("land", {
-- Step 2) retrieve context when player submits the form
--
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "mylandowner:edit" then
return false
end
if formname ~= "mylandowner:edit" then
return false
end
-- Load information
local context = land_formspec_context[player:get_player_name()]
-- Load information
local context = land_formspec_context[player:get_player_name()]
if context then
minetest.chat_send_player(player:get_player_name(), "Id " .. context.id .. " is now called " ..
fields.plot .. " and owned by " .. fields.owner)
if context then
minetest.chat_send_player(player:get_player_name(), "Id " .. context.id .. " is now called " ..
fields.plot .. " and owned by " .. fields.owner)
-- Delete context if it is no longer going to be used
land_formspec_context[player:get_player_name()] = nil
-- Delete context if it is no longer going to be used
land_formspec_context[player:get_player_name()] = nil
return true
else
-- Fail gracefully if the context does not exist.
minetest.chat_send_player(player:get_player_name(), "Something went wrong, try again.")
end
return true
else
-- Fail gracefully if the context does not exist.
minetest.chat_send_player(player:get_player_name(), "Something went wrong, try again.")
end
end)
{% endhighlight %}
@ -252,20 +252,20 @@ the player the chest formspec.
{% highlight lua %}
minetest.register_node("mymod:rightclick", {
description = "Rightclick me!",
tiles = {"mymod_rightclick.png"},
groups = {cracky = 1},
after_place_node = function(pos, placer)
-- This function is run when the chest node is placed.
-- The following code sets the formspec for chest.
-- Meta is a way of storing data onto a node.
description = "Rightclick me!",
tiles = {"mymod_rightclick.png"},
groups = {cracky = 1},
after_place_node = function(pos, placer)
-- This function is run when the chest node is placed.
-- The following code sets the formspec for chest.
-- Meta is a way of storing data onto a node.
local meta = minetest.get_meta(pos)
meta:set_string("formspec",
"size[5,5]"..
"label[1,1;This is shown on right click]"..
local meta = minetest.get_meta(pos)
meta:set_string("formspec",
"size[5,5]"..
"label[1,1;This is shown on right click]"..
"field[1,2;2,1;x;x;]")
end,
end,
on_receive_fields = function(pos, formname, fields, player)
if(fields.quit) then return end
print(fields.x)

View File

@ -5,10 +5,10 @@ root: ../../
---
<div class="notice">
<h2>Experimental Feature</h2>
<h2>Experimental Feature</h2>
The HUD feature will probably be rewritten in an upcoming Minetest release.
Be aware that you may need to update your mods if the API is changed.
The HUD feature will probably be rewritten in an upcoming Minetest release.
Be aware that you may need to update your mods if the API is changed.
</div>
## Introduction
@ -84,11 +84,11 @@ Here is our earlier example, but with comments to explain each part:
{% highlight lua %}
local idx = player:hud_add({
hud_elem_type = "text", -- This is a text element
position = {x = 1, y = 0},
offset = {x=-100, y = 20},
scale = {x = 100, y = 100}, -- Maximum size of text, crops off any out of these bounds
text = "My Text" -- The actual text shown
hud_elem_type = "text", -- This is a text element
position = {x = 1, y = 0},
offset = {x=-100, y = 20},
scale = {x = 100, y = 100}, -- Maximum size of text, crops off any out of these bounds
text = "My Text" -- The actual text shown
})
{% endhighlight %}
@ -99,12 +99,12 @@ Colors are in [Hexadecimal form](http://www.colorpicker.com/).
{% highlight lua %}
local idx = player:hud_add({
hud_elem_type = "text",
position = {x = 1, y = 0},
offset = {x=-100, y = 20},
scale = {x = 100, y = 100},
text = "My Text",
number = 0xFF0000 -- Red
hud_elem_type = "text",
position = {x = 1, y = 0},
offset = {x=-100, y = 20},
scale = {x = 100, y = 100},
text = "My Text",
number = 0xFF0000 -- Red
})
{% endhighlight %}

View File

@ -13,21 +13,21 @@ This chapter assumes that you already know how to create and manipulate
* Basic Concepts.
* Types of Inventories.
* Player Inventories.
* Node Inventories.
* Detached Inventories.
* Player Inventories.
* Node Inventories.
* Detached Inventories.
* InvRef and Lists.
* Type of inventory.
* List sizes.
* List is empty.
* Lua Tables.
* Lua Tables for Lists.
* Type of inventory.
* List sizes.
* List is empty.
* Lua Tables.
* Lua Tables for Lists.
* InvRef, Items and Stacks.
* Adding to a list.
* Checking for room.
* Taking items.
* Contains.
* Manipulating Stacks.
* Adding to a list.
* Checking for room.
* Taking items.
* Contains.
* Manipulating Stacks.
## Basic Concepts
@ -45,17 +45,17 @@ There are three ways you can get inventories:
* **Detached Inventories** - an inventory which is not attached to a node or player.
<figure>
<img src="{{ page.root }}/static/inventories_lists.png" alt="The player inventory formspec, with annotated list names.">
<figcaption>
This image shows the two inventories visible when you press i.
The gray boxes are inventory lists.<br />
The creative inventory, left (in red) is detached and it made up of a
single list.<br />
The player inventory, right (in blue) is a player inventory
and is made up of three lists.<br />
Note that the trash can is a <a href="formspecs.html">formspec</a>
element, and is not part of the inventory.
</figcaption>
<img src="{{ page.root }}/static/inventories_lists.png" alt="The player inventory formspec, with annotated list names.">
<figcaption>
This image shows the two inventories visible when you press i.
The gray boxes are inventory lists.<br />
The creative inventory, left (in red) is detached and it made up of a
single list.<br />
The player inventory, right (in blue) is a player inventory
and is made up of three lists.<br />
Note that the trash can is a <a href="formspecs.html">formspec</a>
element, and is not part of the inventory.
</figcaption>
</figure>
@ -124,11 +124,11 @@ They also have a width, which is used to divide them into a grid.
{% highlight lua %}
if inv:set_size("main", 32) then
inv:set_width("main", 8)
print("size: " .. inv.get_size("main"))
print("width: " .. inv:get_width("main"))
inv:set_width("main", 8)
print("size: " .. inv.get_size("main"))
print("width: " .. inv:get_width("main"))
else
print("Error!")
print("Error!")
end
{% endhighlight %}
@ -140,7 +140,7 @@ a list doesn't have a width or height, only the maximum number of stacks/slots.-
{% highlight lua %}
if inv:is_empty("main") then
print("The list is empty!")
print("The list is empty!")
end
{% endhighlight %}
@ -156,20 +156,20 @@ It will be in this form:
{% highlight lua %}
{
list_one = {
ItemStack,
ItemStack,
ItemStack,
ItemStack,
-- inv:get_size("list_one") elements
},
list_two = {
ItemStack,
ItemStack,
ItemStack,
ItemStack,
-- inv:get_size("list_two") elements
}
list_one = {
ItemStack,
ItemStack,
ItemStack,
ItemStack,
-- inv:get_size("list_one") elements
},
list_two = {
ItemStack,
ItemStack,
ItemStack,
ItemStack,
-- inv:get_size("list_two") elements
}
}
{% endhighlight %}
@ -193,11 +193,11 @@ It will be in this form:
{% highlight lua %}
{
ItemStack,
ItemStack,
ItemStack,
ItemStack,
-- inv:get_size("list_one") elements
ItemStack,
ItemStack,
ItemStack,
ItemStack,
-- inv:get_size("list_one") elements
}
{% endhighlight %}
@ -217,7 +217,7 @@ Please note that the sizes of lists will not change.
local stack = ItemStack("default:stone 99")
local leftover = inv:add_item("main", stack)
if leftover:get_count() > 0 then
print("Inventory is full! " .. leftover:get_count() .. " items weren't added")
print("Inventory is full! " .. leftover:get_count() .. " items weren't added")
end
{% endhighlight %}
@ -227,7 +227,7 @@ end
{% highlight lua %}
if not inv:room_for_item("main", stack) then
print("Not enough room!")
print("Not enough room!")
end
{% endhighlight %}
@ -246,7 +246,7 @@ are stacks of 99 + 95 + 6.
{% highlight lua %}
if not inv:contains_item(listname, stack) then
print("Item not in inventory!")
print("Item not in inventory!")
end
{% endhighlight %}

View File

@ -33,9 +33,9 @@ You could alternatively create a blank ItemStack and fill it using methods:
{% highlight lua %}
local items = ItemStack()
if items:set_name("default:dirt") then
items:set_count(99)
items:set_count(99)
else
print("An error occured!")
print("An error occured!")
end
{% endhighlight %}
@ -57,10 +57,10 @@ print(items:get_name()) -- default:stone
print(items:get_count()) -- 99
if items:set_name("default:dirt") then
print(items:get_name()) -- default:dirt
print(items:get_count()) -- 99
print(items:get_name()) -- default:dirt
print(items:get_count()) -- 99
else
error("This shouldn't happen")
error("This shouldn't happen")
end
{% endhighlight %}

View File

@ -10,10 +10,10 @@ In this chapter we will talk about scripting in Lua, the tools required,
and go over some techniques which you will probably find useful.
* Tools
* Recommended Editors
* Integrated Programming Environments
* Recommended Editors
* Integrated Programming Environments
* Coding in Lua
* Selection
* Selection
* Programming
* Local and Global
* Including other Lua Scripts
@ -26,17 +26,17 @@ depending on what they mean. This allows you to spot mistakes.
{% highlight lua %}
function ctf.post(team,msg)
if not ctf.team(team) then
return false
end
if not ctf.team(team).log then
ctf.team(team).log = {}
end
if not ctf.team(team) then
return false
end
if not ctf.team(team).log then
ctf.team(team).log = {}
end
table.insert(ctf.team(team).log,1,msg)
ctf.save()
table.insert(ctf.team(team).log,1,msg)
ctf.save()
return true
return true
end
{% endhighlight %}
@ -69,7 +69,7 @@ One such IDE is Eclipse with the Koneki Lua plugin:
## Coding in Lua
<div class="notice">
This section is a Work in Progress. May be unclear.
This section is a Work in Progress. May be unclear.
</div>
Programs are a series of commands that run one after another.
@ -138,9 +138,9 @@ The most basic selection is the if statement. It looks like this:
local random_number = math.random(1, 100) -- Between 1 and 100.
if random_number > 50 then
print("Woohoo!")
print("Woohoo!")
else
print("No!")
print("No!")
end
{% endhighlight %}
@ -166,7 +166,7 @@ That doesn't contain every possible operator, and you can combine operators like
{% highlight lua %}
if not A and B then
print("Yay!")
print("Yay!")
end
{% endhighlight %}
@ -180,7 +180,7 @@ local A = 5
local is_equal = (A == 5)
if is_equal then
print("Is equal!")
print("Is equal!")
end
{% endhighlight %}
@ -211,13 +211,13 @@ A local variable is only accessible from where it is defined. Here are some exam
local one = 1
function myfunc()
-- Accessible from within this function
local two = one + one
-- Accessible from within this function
local two = one + one
if two == one then
-- Accessible from within this if statement
local three = one + two
end
if two == one then
-- Accessible from within this if statement
local three = one + two
end
end
{% endhighlight %}
@ -227,7 +227,7 @@ Whereas global variables can be accessed from anywhere in the script file, and f
my_global_variable = "blah"
function one()
my_global_variable = "three"
my_global_variable = "three"
end
print(my_global_variable) -- Output: "blah"
@ -243,11 +243,11 @@ Local variables must be identified as such.
{% highlight lua %}
function one()
foo = "bar"
foo = "bar"
end
function two()
print(dump(foo)) -- Output: "bar"
print(dump(foo)) -- Output: "bar"
end
one()
@ -260,17 +260,17 @@ which show it is a string.
This is sloppy coding, and Minetest will in fact warn you about this:
[WARNING] Assigment to undeclared global 'foo' inside function at init.lua:2
[WARNING] Assigment to undeclared global 'foo' inside function at init.lua:2
To correct this, use "local":
{% highlight lua %}
function one()
local foo = "bar"
local foo = "bar"
end
function two()
print(dump(foo)) -- Output: nil
print(dump(foo)) -- Output: nil
end
one()
@ -286,7 +286,7 @@ as other mods could have functions of the same name.
{% highlight lua %}
local function foo(bar)
return bar * 2
return bar * 2
end
{% endhighlight %}
@ -297,7 +297,7 @@ you add them all into a table with the same name as the mod:
mymod = {}
function mymod.foo(bar)
return "foo" .. bar
return "foo" .. bar
end
-- In another mod, or script:

View File

@ -5,10 +5,10 @@ root: ../../
---
<div class="notice">
<h2>This chapter is incomplete</h2>
<h2>This chapter is incomplete</h2>
Some drawtypes have not been explained yet,
and placeholder images are being used.
Some drawtypes have not been explained yet,
and placeholder images are being used.
</div>
## Introduction
@ -25,12 +25,12 @@ the title of the sections, except in lower case.
* Normal
* Airlike
* Liquid
* FlowingLiquid
* FlowingLiquid
* Glasslike
* Glasslike_Framed
* Glasslike_Framed_Optional
* Glasslike_Framed_Optional
* Allfaces
* Allfaces_Optional
* Allfaces_Optional
* Torchlike
* Nodebox
@ -46,10 +46,10 @@ This article is not complete yet. These drawtypes are missing:
## Normal
<figure class="right_image">
<img src="{{ page.root }}/static/drawtype_normal.png" alt="Normal Drawtype">
<figcaption>
Normal Drawtype
</figcaption>
<img src="{{ page.root }}/static/drawtype_normal.png" alt="Normal Drawtype">
<figcaption>
Normal Drawtype
</figcaption>
</figure>
This is, well, the normal drawtypes.
@ -59,18 +59,18 @@ Notice how you don't need to declare the drawtype.
{% highlight lua %}
minetest.register_node("mymod:diamond", {
description = "Alien Diamond",
tiles = {
"mymod_diamond_up.png",
"mymod_diamond_down.png",
"mymod_diamond_right.png",
"mymod_diamond_left.png",
"mymod_diamond_back.png",
"mymod_diamond_front.png"
},
is_ground_content = true,
groups = {cracky = 3},
drop = "mymod:diamond_fragments"
description = "Alien Diamond",
tiles = {
"mymod_diamond_up.png",
"mymod_diamond_down.png",
"mymod_diamond_right.png",
"mymod_diamond_left.png",
"mymod_diamond_back.png",
"mymod_diamond_front.png"
},
is_ground_content = true,
groups = {cracky = 3},
drop = "mymod:diamond_fragments"
})
{% endhighlight %}
@ -81,34 +81,34 @@ These nodes are see through and thus have no textures.
{% highlight lua %}
minetest.register_node("myair:air", {
description = "MyAir (you hacker you!)",
drawtype = "airlike",
description = "MyAir (you hacker you!)",
drawtype = "airlike",
paramtype = "light",
-- ^ Allows light to propagate through the node with the
-- light value falling by 1 per node.
paramtype = "light",
-- ^ Allows light to propagate through the node with the
-- light value falling by 1 per node.
sunlight_propagates = true, -- Sunlight shines through
walkable = false, -- Would make the player collide with the air node
pointable = false, -- You can't select the node
diggable = false, -- You can't dig the node
buildable_to = true, -- Nodes can be replace this node.
-- (you can place a node and remove the air node
-- that used to be there)
sunlight_propagates = true, -- Sunlight shines through
walkable = false, -- Would make the player collide with the air node
pointable = false, -- You can't select the node
diggable = false, -- You can't dig the node
buildable_to = true, -- Nodes can be replace this node.
-- (you can place a node and remove the air node
-- that used to be there)
air_equivalent = true,
drop = "",
groups = {not_in_creative_inventory=1}
air_equivalent = true,
drop = "",
groups = {not_in_creative_inventory=1}
})
{% endhighlight %}
## Liquid
<figure class="right_image">
<img src="{{ page.root }}/static/drawtype_liquid.png" alt="Liquid Drawtype">
<figcaption>
Liquid Drawtype
</figcaption>
<img src="{{ page.root }}/static/drawtype_liquid.png" alt="Liquid Drawtype">
<figcaption>
Liquid Drawtype
</figcaption>
</figure>
These nodes are complete liquid nodes, the liquid flows outwards from position
@ -118,63 +118,63 @@ For each liquid node you should also have a flowing liquid node.
{% highlight lua %}
-- Some properties have been removed as they are beyond the scope of this chapter.
minetest.register_node("default:water_source", {
drawtype = "liquid",
paramtype = "light",
drawtype = "liquid",
paramtype = "light",
inventory_image = minetest.inventorycube("default_water.png"),
-- ^ this is required to stop the inventory image from being animated
inventory_image = minetest.inventorycube("default_water.png"),
-- ^ this is required to stop the inventory image from being animated
tiles = {
{
name = "default_water_source_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 2.0
}
}
},
tiles = {
{
name = "default_water_source_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 2.0
}
}
},
special_tiles = {
-- New-style water source material (mostly unused)
{
name = "default_water_source_animated.png",
animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 2.0},
backface_culling = false,
}
},
special_tiles = {
-- New-style water source material (mostly unused)
{
name = "default_water_source_animated.png",
animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 2.0},
backface_culling = false,
}
},
--
-- Behavior
--
walkable = false, -- The player falls through
pointable = false, -- The player can't highlight it
diggable = false, -- The player can't dig it
buildable_to = true, -- Nodes can be replace this node
--
-- Behavior
--
walkable = false, -- The player falls through
pointable = false, -- The player can't highlight it
diggable = false, -- The player can't dig it
buildable_to = true, -- Nodes can be replace this node
alpha = 160,
alpha = 160,
--
-- Liquid Properties
--
drowning = 1,
liquidtype = "source",
--
-- Liquid Properties
--
drowning = 1,
liquidtype = "source",
liquid_alternative_flowing = "default:water_flowing",
-- ^ when the liquid is flowing
liquid_alternative_flowing = "default:water_flowing",
-- ^ when the liquid is flowing
liquid_alternative_source = "default:water_source",
-- ^ when the liquid is a source
liquid_alternative_source = "default:water_source",
-- ^ when the liquid is a source
liquid_viscosity = WATER_VISC,
-- ^ how fast
liquid_viscosity = WATER_VISC,
-- ^ how fast
liquid_range = 8,
-- ^ how far
liquid_range = 8,
-- ^ how far
post_effect_color = {a=64, r=100, g=100, b=200},
-- ^ color of screen when the player is submerged
post_effect_color = {a=64, r=100, g=100, b=200},
-- ^ color of screen when the player is submerged
})
{% endhighlight %}
@ -186,32 +186,32 @@ the same as the above example.
## Glasslike
<figure class="right_image">
<img src="{{ page.root }}/static/drawtype_glasslike.png" alt="Glasslike Drawtype">
<figcaption>
Glasslike Drawtype
</figcaption>
<img src="{{ page.root }}/static/drawtype_glasslike.png" alt="Glasslike Drawtype">
<figcaption>
Glasslike Drawtype
</figcaption>
</figure>
When you place multiple glasslike nodes together, you'll notice that the internal
edges are hidden, like this:
<figure>
<img src="{{ page.root }}/static/drawtype_glasslike_edges.png" alt="Glasslike's Edges">
<figcaption>
Glasslike's Edges
</figcaption>
<img src="{{ page.root }}/static/drawtype_glasslike_edges.png" alt="Glasslike's Edges">
<figcaption>
Glasslike's Edges
</figcaption>
</figure>
{% highlight lua %}
minetest.register_node("default:obsidian_glass", {
description = "Obsidian Glass",
drawtype = "glasslike",
tiles = {"default_obsidian_glass.png"},
paramtype = "light",
is_ground_content = false,
sunlight_propagates = true,
sounds = default.node_sound_glass_defaults(),
groups = {cracky=3,oddly_breakable_by_hand=3},
description = "Obsidian Glass",
drawtype = "glasslike",
tiles = {"default_obsidian_glass.png"},
paramtype = "light",
is_ground_content = false,
sunlight_propagates = true,
sounds = default.node_sound_glass_defaults(),
groups = {cracky=3,oddly_breakable_by_hand=3},
})
{% endhighlight %}
@ -221,26 +221,26 @@ This makes the node's edge go around the whole thing with a 3D effect, rather
than individual nodes, like the following:
<figure>
<img src="{{ page.root }}/static/drawtype_glasslike_framed.png" alt="Glasslike_framed's Edges">
<figcaption>
Glasslike_Framed's Edges
</figcaption>
<img src="{{ page.root }}/static/drawtype_glasslike_framed.png" alt="Glasslike_framed's Edges">
<figcaption>
Glasslike_Framed's Edges
</figcaption>
</figure>
{% highlight lua %}
minetest.register_node("default:glass", {
description = "Glass",
drawtype = "glasslike_framed",
description = "Glass",
drawtype = "glasslike_framed",
tiles = {"default_glass.png", "default_glass_detail.png"},
inventory_image = minetest.inventorycube("default_glass.png"),
tiles = {"default_glass.png", "default_glass_detail.png"},
inventory_image = minetest.inventorycube("default_glass.png"),
paramtype = "light",
sunlight_propagates = true, -- Sunlight can shine through block
is_ground_content = false, -- Stops caves from being generated over this node.
paramtype = "light",
sunlight_propagates = true, -- Sunlight can shine through block
is_ground_content = false, -- Stops caves from being generated over this node.
groups = {cracky = 3, oddly_breakable_by_hand = 3},
sounds = default.node_sound_glass_defaults()
groups = {cracky = 3, oddly_breakable_by_hand = 3},
sounds = default.node_sound_glass_defaults()
})
{% endhighlight %}
@ -251,10 +251,10 @@ minetest.register_node("default:glass", {
## Allfaces
<figure class="right_image">
<img src="{{ page.root }}/static/drawtype_allfaces.png" alt="Allfaces drawtype">
<figcaption>
Allfaces drawtype
</figcaption>
<img src="{{ page.root }}/static/drawtype_allfaces.png" alt="Allfaces drawtype">
<figcaption>
Allfaces drawtype
</figcaption>
</figure>
Allfaces nodes are partially transparent nodes - they have holes on
@ -264,9 +264,9 @@ Leaves in vanilla minetest_game use this drawtype.
{% highlight lua %}
minetest.register_node("default:leaves", {
description = "Leaves",
drawtype = "allfaces_optional",
tiles = {"default_leaves.png"}
description = "Leaves",
drawtype = "allfaces_optional",
tiles = {"default_leaves.png"}
})
{% endhighlight %}
@ -285,38 +285,38 @@ items which need to have different textures depending on where they are placed.
{% highlight lua %}
minetest.register_node("foobar:torch", {
description = "Foobar Torch",
drawtype = "torchlike",
tiles = {
{"foobar_torch_floor.png"},
{"foobar_torch_ceiling.png"},
{"foobar_torch_wall.png"}
},
inventory_image = "foobar_torch_floor.png",
wield_image = "default_torch_floor.png",
light_source = LIGHT_MAX-1,
description = "Foobar Torch",
drawtype = "torchlike",
tiles = {
{"foobar_torch_floor.png"},
{"foobar_torch_ceiling.png"},
{"foobar_torch_wall.png"}
},
inventory_image = "foobar_torch_floor.png",
wield_image = "default_torch_floor.png",
light_source = LIGHT_MAX-1,
-- Determines how the torch is selected, ie: the wire box around it.
-- each value is { x1, y1, z1, x2, y2, z2 }
-- (x1, y1, y1) is the bottom front left corner
-- (x2, y2, y2) is the opposite - top back right.
-- Similar to the nodebox format.
selection_box = {
type = "wallmounted",
wall_top = {-0.1, 0.5-0.6, -0.1, 0.1, 0.5, 0.1},
wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
}
-- Determines how the torch is selected, ie: the wire box around it.
-- each value is { x1, y1, z1, x2, y2, z2 }
-- (x1, y1, y1) is the bottom front left corner
-- (x2, y2, y2) is the opposite - top back right.
-- Similar to the nodebox format.
selection_box = {
type = "wallmounted",
wall_top = {-0.1, 0.5-0.6, -0.1, 0.1, 0.5, 0.1},
wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
}
})
{% endhighlight %}
## Nodebox
<figure class="right_image">
<img src="{{ page.root }}/static/drawtype_nodebox.gif" alt="Nodebox drawtype">
<figcaption>
Nodebox drawtype
</figcaption>
<img src="{{ page.root }}/static/drawtype_nodebox.gif" alt="Nodebox drawtype">
<figcaption>
Nodebox drawtype
</figcaption>
</figure>
Nodeboxes allow you to create a node which is not cubic, but is instead made out
@ -324,15 +324,15 @@ of as many cuboids as you like.
{% highlight lua %}
minetest.register_node("stairs:stair_stone", {
drawtype = "nodebox",
paramtype = "light",
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 0, 0.5},
{-0.5, 0, 0, 0.5, 0.5, 0.5},
},
}
drawtype = "nodebox",
paramtype = "light",
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 0, 0.5},
{-0.5, 0, 0, 0.5, 0.5, 0.5},
},
}
})
{% endhighlight %}
@ -357,24 +357,24 @@ Sometimes you want different nodeboxes for when it is placed on the floor, wall,
{% highlight lua %}
minetest.register_node("default:sign_wall", {
drawtype = "nodebox",
node_box = {
type = "wallmounted",
drawtype = "nodebox",
node_box = {
type = "wallmounted",
-- Ceiling
wall_top = {
{-0.4375, 0.4375, -0.3125, 0.4375, 0.5, 0.3125}
},
-- Ceiling
wall_top = {
{-0.4375, 0.4375, -0.3125, 0.4375, 0.5, 0.3125}
},
-- Floor
wall_bottom = {
{-0.4375, -0.5, -0.3125, 0.4375, -0.4375, 0.3125}
},
-- Floor
wall_bottom = {
{-0.4375, -0.5, -0.3125, 0.4375, -0.4375, 0.3125}
},
-- Wall
wall_side = {
{-0.5, -0.3125, -0.4375, -0.4375, 0.3125, 0.4375}
}
},
-- Wall
wall_side = {
{-0.5, -0.3125, -0.4375, -0.4375, 0.3125, 0.4375}
}
},
})
{% endhighlight %}

View File

@ -53,11 +53,11 @@ local meta = minetest.get_meta(pos)
local value = meta:get_string("key")
if value then
print(value)
print(value)
else
-- value == nil
-- metadata of key "key" does not exist
print(value)
-- value == nil
-- metadata of key "key" does not exist
print(value)
end
{% endhighlight %}
@ -75,9 +75,9 @@ In order to do booleans, you should use `get_string` and `minetest.is_yes`:
local value = minetest.is_yes(meta:get_string("key"))
if value then
print("is yes")
print("is yes")
else
print("is no")
print("is no")
end
{% endhighlight %}

View File

@ -23,7 +23,7 @@ Each item, whether that be a node, craftitem, tool, or entity, has an item strin
This is sometimes referred to as registered name or just name.
A string in programming terms is a piece of text.
modname:itemname
modname:itemname
The modname is the name of the folder your mod is in.
You may call the itemname anything you like; however, it should be relevant to
@ -55,8 +55,8 @@ They are used in recipes to create other items, or they can be used by the playe
{% highlight lua %}
minetest.register_craftitem("mymod:diamond_fragments", {
description = "Alien Diamond Fragments",
inventory_image = "mymod_diamond_fragments.png"
description = "Alien Diamond Fragments",
inventory_image = "mymod_diamond_fragments.png"
})
{% endhighlight %}
@ -70,9 +70,9 @@ Foods are items that cure health. To create a food item you need to define the o
{% highlight lua %}
minetest.register_craftitem("mymod:mudpie", {
description = "Alien Mud Pie",
inventory_image = "myfood_mudpie.png",
on_use = minetest.item_eat(20)
description = "Alien Mud Pie",
inventory_image = "myfood_mudpie.png",
on_use = minetest.item_eat(20)
})
{% endhighlight %}
@ -83,7 +83,7 @@ Hitpoints don't have to be integers (whole numbers), they can be decimals.
Sometimes you may want a food to be replaced with another item when being eaten,
for example smaller pieces of cake or bones after eating meat. To do this, use:
minetest.item_eat(hp, replace_with_item)
minetest.item_eat(hp, replace_with_item)
Where replace_with_item is an item string.
@ -94,28 +94,28 @@ such as send a message to the player?
{% highlight lua %}
minetest.register_craftitem("mymod:mudpie", {
description = "Alien Mud Pie",
inventory_image = "myfood_mudpie.png",
on_use = function(itemstack, user, pointed_thing)
hp_change = 20
replace_with_item = nil
description = "Alien Mud Pie",
inventory_image = "myfood_mudpie.png",
on_use = function(itemstack, user, pointed_thing)
hp_change = 20
replace_with_item = nil
minetest.chat_send_player(user:get_player_name(), "You ate an alien mud pie!")
minetest.chat_send_player(user:get_player_name(), "You ate an alien mud pie!")
-- Support for hunger mods using minetest.register_on_item_eat
for _ , callback in pairs(minetest.registered_on_item_eats) do
local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing)
if result then
return result
end
end
-- Support for hunger mods using minetest.register_on_item_eat
for _ , callback in pairs(minetest.registered_on_item_eats) do
local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing)
if result then
return result
end
end
if itemstack:take_item() ~= nil then
user:set_hp(user:get_hp() + hp_change)
end
if itemstack:take_item() ~= nil then
user:set_hp(user:get_hp() + hp_change)
end
return itemstack
end
return itemstack
end
})
{% endhighlight %}
@ -133,10 +133,10 @@ definition table; however, you need to set the textures for the faces of the cub
{% highlight lua %}
minetest.register_node("mymod:diamond", {
description = "Alien Diamond",
tiles = {"mymod_diamond.png"},
is_ground_content = true,
groups = {cracky=3, stone=1}
description = "Alien Diamond",
tiles = {"mymod_diamond.png"},
is_ground_content = true,
groups = {cracky=3, stone=1}
})
{% endhighlight %}
@ -155,19 +155,19 @@ a negative direction means that it is facing negative co-ordinates.
{% highlight lua %}
minetest.register_node("mymod:diamond", {
description = "Alien Diamond",
tiles = {
"mymod_diamond_up.png",
"mymod_diamond_down.png",
"mymod_diamond_right.png",
"mymod_diamond_left.png",
"mymod_diamond_back.png",
"mymod_diamond_front.png"
},
is_ground_content = true,
groups = {cracky = 3},
drop = "mymod:diamond_fragments"
-- ^ Rather than dropping diamond, drop mymod:diamond_fragments
description = "Alien Diamond",
tiles = {
"mymod_diamond_up.png",
"mymod_diamond_down.png",
"mymod_diamond_right.png",
"mymod_diamond_left.png",
"mymod_diamond_back.png",
"mymod_diamond_front.png"
},
is_ground_content = true,
groups = {cracky = 3},
drop = "mymod:diamond_fragments"
-- ^ Rather than dropping diamond, drop mymod:diamond_fragments
})
{% endhighlight %}
@ -182,7 +182,7 @@ identified by the ``type`` property.
* shapeless - It doesn't matter where the ingredients are,
just that there is the right amount.
* cooking - Recipes for the furnace to use.
* fuel - Defines items which can be burned in furnaces.
* fuel - Defines items which can be burned in furnaces.
* tool_repair - Used to allow the repairing of tools.
Craft recipes do not use Item Strings to uniquely identify themselves.
@ -196,12 +196,12 @@ right place for it to work.
{% highlight lua %}
minetest.register_craft({
output = "mymod:diamond_chair 99",
recipe = {
{"mymod:diamond_fragments", "", ""},
{"mymod:diamond_fragments", "mymod:diamond_fragments", ""},
{"mymod:diamond_fragments", "mymod:diamond_fragments", ""}
}
output = "mymod:diamond_chair 99",
recipe = {
{"mymod:diamond_fragments", "", ""},
{"mymod:diamond_fragments", "mymod:diamond_fragments", ""},
{"mymod:diamond_fragments", "mymod:diamond_fragments", ""}
}
})
{% endhighlight %}
@ -219,12 +219,12 @@ allows the recipe to be crafted if it was all moved one place to the right.
{% highlight lua %}
minetest.register_craft({
output = "mymod:diamond_chair",
recipe = {
{"mymod:diamond_fragments", ""},
{"mymod:diamond_fragments", "mymod:diamond_fragments"},
{"mymod:diamond_fragments", "mymod:diamond_fragments"}
}
output = "mymod:diamond_chair",
recipe = {
{"mymod:diamond_fragments", ""},
{"mymod:diamond_fragments", "mymod:diamond_fragments"},
{"mymod:diamond_fragments", "mymod:diamond_fragments"}
}
})
{% endhighlight %}
@ -237,9 +237,9 @@ need to be in any specific place for it to work.
{% highlight lua %}
minetest.register_craft({
type = "shapeless",
output = "mymod:diamond",
recipe = {"mymod:diamond_fragments", "mymod:diamond_fragments", "mymod:diamond_fragments"}
type = "shapeless",
output = "mymod:diamond",
recipe = {"mymod:diamond_fragments", "mymod:diamond_fragments", "mymod:diamond_fragments"}
})
{% endhighlight %}
@ -256,10 +256,10 @@ For example, you use a cooking recipe to turn ores into bars.
{% highlight lua %}
minetest.register_craft({
type = "cooking",
output = "mymod:diamond_fragments",
recipe = "default:coalblock",
cooktime = 10,
type = "cooking",
output = "mymod:diamond_fragments",
recipe = "default:coalblock",
cooktime = 10,
})
{% endhighlight %}
@ -279,9 +279,9 @@ what can be burned in furnaces and other cooking tools from mods.
{% highlight lua %}
minetest.register_craft({
type = "fuel",
recipe = "mymod:diamond",
burntime = 300,
type = "fuel",
recipe = "mymod:diamond",
burntime = 300,
})
{% endhighlight %}

View File

@ -21,13 +21,13 @@ puts the caller in low G:
{% highlight lua %}
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)
})
end
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)
})
end
})
{% endhighlight %}

View File

@ -44,8 +44,8 @@ given to them.
{% highlight lua %}
minetest.register_privilege("vote", {
description = "Can vote on issues",
give_to_singleplayer = true
description = "Can vote on issues",
give_to_singleplayer = true
})
{% endhighlight %}
@ -54,7 +54,7 @@ value when not specified:
{% highlight lua %}
minetest.register_privilege("vote", {
description = "Can vote on issues"
description = "Can vote on issues"
})
{% endhighlight %}
@ -64,8 +64,8 @@ There is a quicker way of checking that a player has all the required privileges
{% highlight lua %}
local has, missing = minetest.check_player_privs(player_or_name, {
interact = true,
vote = true })
interact = true,
vote = true })
{% endhighlight %}
`has` is true if the player has all the privileges needed.\\
@ -74,18 +74,18 @@ of missing privileges<sup>[checking needed]</sup>.
{% highlight lua %}
if minetest.check_player_privs(name, {interact=true, vote=true}) then
print("Player has all privs!")
print("Player has all privs!")
else
print("Player is missing some privs!")
print("Player is missing some privs!")
end
local has, missing = minetest.check_player_privs(name, {
interact = true,
vote = true })
interact = true,
vote = true })
if has then
print("Player has all privs!")
print("Player has all privs!")
else
print("Player is missing privs: " .. dump(missing))
print("Player is missing privs: " .. dump(missing))
end
{% endhighlight %}
@ -103,9 +103,9 @@ Running that example may give the following:
{% highlight lua %}
{
fly = true,
interact = true,
shout = true
fly = true,
interact = true,
shout = true
}
{% endhighlight %}
@ -113,8 +113,8 @@ To set a player's privs, you use `minetest.set_player_privs`:
{% highlight lua %}
minetest.set_player_privs(name, {
interact = true,
shout = true })
interact = true,
shout = true })
{% endhighlight %}
To grant a player some privs, you would use a mixture of those two:
@ -128,12 +128,12 @@ minetest.set_player_privs(name, privs)
## Adding privileges to basic_privs
<div class="notice">
<h2>Workaround / PR pending</h2>
<h2>Workaround / PR pending</h2>
This is a workaround for a missing feature.
I have submitted a
<a href="https://github.com/minetest/minetest/pull/3976">pull request / patch</a>
to make it so you don't need to edit builtin to add a priv to basic_privs.
This is a workaround for a missing feature.
I have submitted a
<a href="https://github.com/minetest/minetest/pull/3976">pull request / patch</a>
to make it so you don't need to edit builtin to add a priv to basic_privs.
</div>
To allow people with basic_privs to grant and revoke your priv, you'll
@ -143,8 +143,8 @@ In both grant and revoke, change the following if statement:
{% highlight lua %}
if priv ~= "interact" and priv ~= "shout" and
not core.check_player_privs(name, {privs=true}) then
return false, "Your privileges are insufficient."
not core.check_player_privs(name, {privs=true}) then
return false, "Your privileges are insufficient."
end
{% endhighlight %}
@ -152,7 +152,7 @@ For example, to add vote:
{% highlight lua %}
if priv ~= "interact" and priv ~= "shout" and priv ~= "vote" and
not core.check_player_privs(name, {privs=true}) then
return false, "Your privileges are insufficient."
not core.check_player_privs(name, {privs=true}) then
return false, "Your privileges are insufficient."
end
{% endhighlight %}

View File

@ -42,29 +42,29 @@ You license your code under LGPL 2.1 and your art under CC-BY-SA.
Add this copyright notice to your README.txt, or as a new file called LICENSE.txt
License for Code
----------------
License for Code
----------------
Copyright (C) 2010-2013 Your Name <emailaddress>
Copyright (C) 2010-2013 Your Name <emailaddress>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
License for Textures, Models and Sounds
---------------------------------------
License for Textures, Models and Sounds
---------------------------------------
CC-BY-SA 3.0 UNPORTED. Created by Your Name
CC-BY-SA 3.0 UNPORTED. Created by Your Name
### WTFPL or CC0
@ -97,8 +97,8 @@ Be concise without being too vague. This is displayed in the mod store.
For example:
GOOD: Adds soups, cakes, bakes and juices. The food mod which supports the most ingredients.
BAD: The food mod for Minetest.
GOOD: Adds soups, cakes, bakes and juices. The food mod which supports the most ingredients.
BAD: The food mod for Minetest.
### screenshot.png
@ -152,10 +152,10 @@ On the create a topic page, see below, go to the "Upload Attachment" tab at the
Click browse and select the zipped file. I suggest that you enter the version of your mod in the comment field.
<figure>
<img src="{{ page.root }}/static/releasing_attachments.png" alt="Upload Attachment">
<figcaption>
Upload Attachment tab.
</figcaption>
<img src="{{ page.root }}/static/releasing_attachments.png" alt="Upload Attachment">
<figcaption>
Upload Attachment tab.
</figcaption>
</figure>
## Forum Topic
@ -184,30 +184,30 @@ You should also include screenshots of your mod in action, if relevant.
Here is an example. The Minetest forum uses bbcode for formating.
Adds magic, rainbows and other special things.
Adds magic, rainbows and other special things.
See download attached.
See download attached.
[b]Version:[/b] 1.1
[b]License:[/b] LGPL 2.1 or later
[b]Version:[/b] 1.1
[b]License:[/b] LGPL 2.1 or later
Dependencies: default mod (found in minetest_game)
Dependencies: default mod (found in minetest_game)
Report bugs or request help on the forum topic.
Report bugs or request help on the forum topic.
[h]Installation[/h]
[h]Installation[/h]
Unzip the archive, rename the folder to to modfoldername and
place it in minetest/mods/minetest/
Unzip the archive, rename the folder to to modfoldername and
place it in minetest/mods/minetest/
( GNU/Linux: If you use a system-wide installation place
it in ~/.minetest/mods/minetest/. )
( GNU/Linux: If you use a system-wide installation place
it in ~/.minetest/mods/minetest/. )
( If you only want this to be used in a single world, place
the folder in worldmods/ in your worlddirectory. )
( If you only want this to be used in a single world, place
the folder in worldmods/ in your worlddirectory. )
For further information or help see:
[url]http://wiki.minetest.com/wiki/Installing_Mods[/url]
For further information or help see:
[url]http://wiki.minetest.com/wiki/Installing_Mods[/url]
If you modify the above example for your mod topic, remember to
change "modfldername" to the name of the folder your mod should be
@ -224,16 +224,16 @@ Subject of topic must be in one of these formats:
### Profit
<figure>
<img src="{{ page.root }}/static/releasing_profit.png" alt="Profit">
<figcaption style="display:none;">
Profit
</figcaption>
<img src="{{ page.root }}/static/releasing_profit.png" alt="Profit">
<figcaption style="display:none;">
Profit
</figcaption>
</figure>
## Appendix: Readme and Forum Generator
<noscript>
<p>Javascript is required for this section!</p>
<p>Javascript is required for this section!</p>
</noscript>
Title: <input id="t_title" value="My Super Special Mod"><br />
@ -264,10 +264,10 @@ Unzip the archive, rename the folder to mysuperspecial and
place it in minetest/mods/
( GNU/Linux: If you use a system-wide installation place
it in ~/.minetest/mods/. )
it in ~/.minetest/mods/. )
( If you only want this to be used in a single world, place
the folder in worldmods/ in your worlddirectory. )
the folder in worldmods/ in your worlddirectory. )
For further information or help see:
http://wiki.minetest.com/wiki/Installing_Mods</code></pre>
@ -287,92 +287,92 @@ Unzip the archive, rename the folder to mysuperspecial and
place it in minetest/mods/
( GNU/Linux: If you use a system-wide installation place
it in ~/.minetest/mods/. )
it in ~/.minetest/mods/. )
( If you only want this to be used in a single world, place
the folder in worldmods/ in your worlddirectory. )
the folder in worldmods/ in your worlddirectory. )
For further information or help see:
http://wiki.minetest.com/wiki/Installing_Mods</code></pre>
<script src="http://blog.rubenwardy.com/static/jquery.min.js"></script>
<script>function regen() {
var title = $("#t_title").val();
var name = $("#t_name").val();
var desc = $("#t_desc").val();
var version = $("#t_version").val();
var license = $("#t_license").val();
var dep = $("#t_dep").val();
var add = $("#t_add").val();
var title = $("#t_title").val();
var name = $("#t_name").val();
var desc = $("#t_desc").val();
var version = $("#t_version").val();
var license = $("#t_license").val();
var dep = $("#t_dep").val();
var add = $("#t_add").val();
var download = $("#t_download").val();
var download = $("#t_download").val();
{
var res = ((title.length > 0) ? title : name) + "\n";
var header_count = res.length - 1;
for (var i = 0; i < header_count; i++) {
res += "=";
}
res += "\n\n";
{
var res = ((title.length > 0) ? title : name) + "\n";
var header_count = res.length - 1;
for (var i = 0; i < header_count; i++) {
res += "=";
}
res += "\n\n";
res += desc + "\n\n";
res += desc + "\n\n";
if (version != "") {
res += "Version: " + version + "\n";
}
if (version != "") {
res += "Version: " + version + "\n";
}
res += "License: " + license + "\n";
res += "Dependencies: " + dep + "\n\n";
res += "License: " + license + "\n";
res += "Dependencies: " + dep + "\n\n";
if (add != "") {
res += add + "\n\n";
}
if (add != "") {
res += add + "\n\n";
}
res += "Installation\n------------\n\nUnzip the archive, rename the folder to ";
res += name + " and\nplace it in minetest/mods/\n\n";
res += "Installation\n------------\n\nUnzip the archive, rename the folder to ";
res += name + " and\nplace it in minetest/mods/\n\n";
res += "( GNU/Linux: If you use a system-wide installation place\n" +
"\tit in ~/.minetest/mods/. )\n\n" +
"( If you only want this to be used in a single world, place\n" +
"\tthe folder in worldmods/ in your worlddirectory. )\n\n" +
"For further information or help see:\n" +
"http://wiki.minetest.com/wiki/Installing_Mods\n";
res += "( GNU/Linux: If you use a system-wide installation place\n" +
"\tit in ~/.minetest/mods/. )\n\n" +
"( If you only want this to be used in a single world, place\n" +
"\tthe folder in worldmods/ in your worlddirectory. )\n\n" +
"For further information or help see:\n" +
"http://wiki.minetest.com/wiki/Installing_Mods\n";
$("#readme").text(res);
}
$("#readme").text(res);
}
{
var res = desc + "\n\n";
{
var res = desc + "\n\n";
if (version != "") {
res += "[b]Version:[/b] " + version + "\n";
}
if (version != "") {
res += "[b]Version:[/b] " + version + "\n";
}
res += "[b]License:[/b] " + license + "\n";
res += "[b]Dependencies:[/b] " + dep + "\n";
res += "[b]License:[/b] " + license + "\n";
res += "[b]Dependencies:[/b] " + dep + "\n";
res += "[b]Download:[/b] " + download + "\n\n";
res += "[b]Download:[/b] " + download + "\n\n";
if (add != "") {
res += add + "\n\n";
}
if (add != "") {
res += add + "\n\n";
}
res += "[h]Installation[/h]\n\nUnzip the archive, rename the folder to ";
res += name + " and\nplace it in minetest/mods/\n\n";
res += "[h]Installation[/h]\n\nUnzip the archive, rename the folder to ";
res += name + " and\nplace it in minetest/mods/\n\n";
res += "( GNU/Linux: If you use a system-wide installation place\n" +
"\tit in ~/.minetest/mods/. )\n\n" +
"( If you only want this to be used in a single world, place\n" +
"\tthe folder in worldmods/ in your worlddirectory. )\n\n" +
"For further information or help see:\n" +
"http://wiki.minetest.com/wiki/Installing_Mods\n";
res += "( GNU/Linux: If you use a system-wide installation place\n" +
"\tit in ~/.minetest/mods/. )\n\n" +
"( If you only want this to be used in a single world, place\n" +
"\tthe folder in worldmods/ in your worlddirectory. )\n\n" +
"For further information or help see:\n" +
"http://wiki.minetest.com/wiki/Installing_Mods\n";
$("#forum").text(res);
}
$("#forum").text(res);
}
}
$(function() {
jQuery('input').on('input propertychange paste', regen);
jQuery('textarea').on('input propertychange paste', regen);
jQuery('input').on('input propertychange paste', regen);
jQuery('textarea').on('input propertychange paste', regen);
});
</script>

View File

@ -45,12 +45,12 @@ Written by rubenwardy.\\
License: [CC-BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)
<!--<form class="leave_comment" action="http://pooleapp.com/stash/74bf2dfb-4c01-423c-b48a-e002ed70bbc1/" method="post">
<input type="hidden" name="redirect_to"
value="http://rubenwardy.com/minetest_modding_book/thank_you.html" />
Nickname (optional): <input class="name" name="name" placeholder="Your Name" type="text"><br />
Contact method (email or forum name, optional): <input name="contact" type="text"><br />
Feedback:
<textarea name="comment" required="" style="display:block;min-width: 90%;min-height:100px;"></textarea>
<input type="hidden" name="redirect_to"
value="http://rubenwardy.com/minetest_modding_book/thank_you.html" />
Nickname (optional): <input class="name" name="name" placeholder="Your Name" type="text"><br />
Contact method (email or forum name, optional): <input name="contact" type="text"><br />
Feedback:
<textarea name="comment" required="" style="display:block;min-width: 90%;min-height:100px;"></textarea>
<input value="Leave Feedback" type="submit">
<input value="Leave Feedback" type="submit">
</form>-->