Wrap code
This commit is contained in:
parent
2e560e50c8
commit
04753b8ff6
@ -55,8 +55,8 @@ To find out if a mod name is available, try searching for it on
|
|||||||
[content.minetest.net](https://content.minetest.net).
|
[content.minetest.net](https://content.minetest.net).
|
||||||
|
|
||||||
mymod
|
mymod
|
||||||
├── init.lua (required) - The main scripting code file. Runs when the game loads.
|
├── init.lua (required) - Runs when the game loads.
|
||||||
├── mod.conf (recommended) - Mod metadata file. Contains description and dependencies.
|
├── mod.conf (recommended) - Contains description and dependencies.
|
||||||
├── textures (optional)
|
├── textures (optional)
|
||||||
│ └── ... any textures or images
|
│ └── ... any textures or images
|
||||||
├── sounds (optional)
|
├── sounds (optional)
|
||||||
@ -110,7 +110,7 @@ and moved together. They are useful if you want to supply multiple mods to
|
|||||||
a player but don't want to make them download each one individually.
|
a player but don't want to make them download each one individually.
|
||||||
|
|
||||||
modpack1
|
modpack1
|
||||||
├── modpack.lua (required) - signals that this is a mod pack, content does not matter
|
├── modpack.lua (required) - signals that this is a mod pack
|
||||||
├── mod1
|
├── mod1
|
||||||
│ └── ... mod files
|
│ └── ... mod files
|
||||||
└── mymod (optional)
|
└── mymod (optional)
|
||||||
|
@ -262,7 +262,7 @@ which show it is a string.
|
|||||||
|
|
||||||
This is sloppy coding, and Minetest will in fact warn about this:
|
This is sloppy coding, and Minetest will in fact warn about this:
|
||||||
|
|
||||||
[WARNING] Assigment to undeclared global 'foo' inside function at init.lua:2
|
Assignment to undeclared global 'foo' inside function at init.lua:2
|
||||||
|
|
||||||
To correct this, use "local":
|
To correct this, use "local":
|
||||||
|
|
||||||
|
@ -127,7 +127,8 @@ Detached inventories need to be created before then can be retrieved -
|
|||||||
this will be covered latter.
|
this will be covered latter.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local inv = minetest.get_inventory({ type="detached", name="inventory_name" })
|
local inv = minetest.get_inventory({
|
||||||
|
type="detached", name="inventory_name" })
|
||||||
```
|
```
|
||||||
|
|
||||||
The location of an inventory reference can be found like so:
|
The location of an inventory reference can be found like so:
|
||||||
@ -185,7 +186,8 @@ To add items to a list named `"main"`, whilst respecting any maximum stack sizes
|
|||||||
local stack = ItemStack("default:stone 99")
|
local stack = ItemStack("default:stone 99")
|
||||||
local leftover = inv:add_item("main", stack)
|
local leftover = inv:add_item("main", stack)
|
||||||
if leftover:get_count() > 0 then
|
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
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -253,7 +253,11 @@ where the ingredients are placed, just that they're there.
|
|||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
type = "shapeless",
|
type = "shapeless",
|
||||||
output = "mymod:diamond 3",
|
output = "mymod:diamond 3",
|
||||||
recipe = {"mymod:diamond_fragments", "mymod:diamond_fragments", "mymod:diamond_fragments"}
|
recipe = {
|
||||||
|
"mymod:diamond_fragments",
|
||||||
|
"mymod:diamond_fragments",
|
||||||
|
"mymod:diamond_fragments",
|
||||||
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -359,7 +363,11 @@ minetest.register_tool("mymod:tool", {
|
|||||||
full_punch_interval = 1.5,
|
full_punch_interval = 1.5,
|
||||||
max_drop_level = 1,
|
max_drop_level = 1,
|
||||||
groupcaps = {
|
groupcaps = {
|
||||||
crumbly = { maxlevel=2, uses=20, times={[1]=1.60, [2]=1.20, [3]=0.80} },
|
crumbly = {
|
||||||
|
maxlevel = 2,
|
||||||
|
uses = 20,
|
||||||
|
times = { [1]=1.60, [2]=1.20, [3]=0.80 }
|
||||||
|
},
|
||||||
},
|
},
|
||||||
damage_groups = {fleshy=2},
|
damage_groups = {fleshy=2},
|
||||||
},
|
},
|
||||||
|
@ -29,7 +29,7 @@ write an ABM.
|
|||||||
```lua
|
```lua
|
||||||
minetest.register_node("aliens:grass", {
|
minetest.register_node("aliens:grass", {
|
||||||
description = "Alien Grass",
|
description = "Alien Grass",
|
||||||
light_source = 3, -- The node radiates light. Values can be from 1 to 15
|
light_source = 3, -- The node radiates light. Min 0, max 14
|
||||||
tiles = {"aliens_grass.png"},
|
tiles = {"aliens_grass.png"},
|
||||||
groups = {choppy=1},
|
groups = {choppy=1},
|
||||||
on_use = minetest.item_eat(20)
|
on_use = minetest.item_eat(20)
|
||||||
@ -40,8 +40,10 @@ minetest.register_abm({
|
|||||||
neighbors = {"default:water_source", "default:water_flowing"},
|
neighbors = {"default:water_source", "default:water_flowing"},
|
||||||
interval = 10.0, -- Run every 10 seconds
|
interval = 10.0, -- Run every 10 seconds
|
||||||
chance = 50, -- Select every 1 in 50 nodes
|
chance = 50, -- Select every 1 in 50 nodes
|
||||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
action = function(pos, node, active_object_count,
|
||||||
minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "aliens:grass"})
|
active_object_count_wider)
|
||||||
|
local pos = {x = pos.x, y = pos.y + 1, z = pos.z}
|
||||||
|
minetest.set_node(pos, {name = "aliens:grass"})
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
@ -38,14 +38,6 @@ will be generated up to the map generation limit (`mapgen_limit`) which is set
|
|||||||
at its maximum value, 31000, by default. Existing MapBlocks can however be
|
at its maximum value, 31000, by default. Existing MapBlocks can however be
|
||||||
loaded from the world database outside of the generation limit.
|
loaded from the world database outside of the generation limit.
|
||||||
|
|
||||||
|
|
||||||
<!--Multiple MapBlocks are generated at a time in groups called *MapChunks*. Each
|
|
||||||
MapChunk is by default 5x5x5<sup>1</sup> MapBlocks, which is 80x80x80 nodes.
|
|
||||||
The size of a MapChunk can change using the chunk_size setting but will always
|
|
||||||
be a cube. -->
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Reading
|
## Reading
|
||||||
|
|
||||||
### Reading Nodes
|
### Reading Nodes
|
||||||
@ -97,7 +89,8 @@ nearby. You should then use a function which can find multiple nodes in area:
|
|||||||
```lua
|
```lua
|
||||||
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
||||||
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
||||||
local pos_list = minetest.find_nodes_in_area(pos1, pos2, { "default:mese" })
|
local pos_list =
|
||||||
|
minetest.find_nodes_in_area(pos1, pos2, { "default:mese" })
|
||||||
local grow_speed = 1 + #pos_list
|
local grow_speed = 1 + #pos_list
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -108,7 +101,8 @@ unfortunately, need to manually check the range ourselves.
|
|||||||
```lua
|
```lua
|
||||||
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
|
||||||
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
|
||||||
local pos_list = minetest.find_nodes_in_area(pos1, pos2, { "default:mese" })
|
local pos_list =
|
||||||
|
minetest.find_nodes_in_area(pos1, pos2, { "default:mese" })
|
||||||
local grow_speed = 1
|
local grow_speed = 1
|
||||||
for i=1, #pos_list do
|
for i=1, #pos_list do
|
||||||
local delta = vector.subtract(pos_list[i], pos)
|
local delta = vector.subtract(pos_list[i], pos)
|
||||||
@ -187,7 +181,8 @@ Minetest will call `emerge_callback` whenever it loads a block, with some
|
|||||||
progress information.
|
progress information.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local function emerge_callback(pos, action, num_calls_remaining, context)
|
local function emerge_callback(pos, action,
|
||||||
|
num_calls_remaining, context)
|
||||||
-- On first call, record number of blocks
|
-- On first call, record number of blocks
|
||||||
if not context.total_blocks then
|
if not context.total_blocks then
|
||||||
context.total_blocks = num_calls_remaining + 1
|
context.total_blocks = num_calls_remaining + 1
|
||||||
@ -202,8 +197,9 @@ local function emerge_callback(pos, action, num_calls_remaining, context)
|
|||||||
minetest.chat_send_all("Finished loading blocks!")
|
minetest.chat_send_all("Finished loading blocks!")
|
||||||
end
|
end
|
||||||
local perc = 100 * context.loaded_blocks / context.total_blocks
|
local perc = 100 * context.loaded_blocks / context.total_blocks
|
||||||
minetest.chat_send_all(string.format("Loading blocks %d/%d (%.2f%%)",
|
local msg = string.format("Loading blocks %d/%d (%.2f%%)",
|
||||||
context.loaded_blocks, context.total_blocks, perc)
|
context.loaded_blocks, context.total_blocks, perc)
|
||||||
|
minetest.chat_send_all(msg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
@ -132,10 +132,11 @@ A complete list can be found in [lua_api.txt]({{ page.root }}/lua_api.html#regis
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
function MyEntity:on_step(dtime)
|
function MyEntity:on_step(dtime)
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
|
local pos_down = vector.subtract(pos, vector.new(0, 1, 0))
|
||||||
|
|
||||||
local delta
|
local delta
|
||||||
if minetest.get_node(vector.subtract(pos, vector.new(0, 1, 0))).name == "air" then
|
if minetest.get_node(pos_down).name == "air" then
|
||||||
delta = vector.new(0, -1, 0)
|
delta = vector.new(0, -1, 0)
|
||||||
elseif minetest.get_node(pos).name == "air" then
|
elseif minetest.get_node(pos).name == "air" then
|
||||||
delta = vector.new(0, 0, 1)
|
delta = vector.new(0, 0, 1)
|
||||||
|
@ -170,9 +170,11 @@ can be painful for the user to set up.
|
|||||||
```lua
|
```lua
|
||||||
local backend
|
local backend
|
||||||
if use_database then
|
if use_database then
|
||||||
backend = dofile(minetest.get_modpath("mymod") .. "/backend_sqlite.lua")
|
backend =
|
||||||
|
dofile(minetest.get_modpath("mymod") .. "/backend_sqlite.lua")
|
||||||
else
|
else
|
||||||
backend = dofile(minetest.get_modpath("mymod") .. "/backend_storage.lua")
|
backend =
|
||||||
|
dofile(minetest.get_modpath("mymod") .. "/backend_storage.lua")
|
||||||
end
|
end
|
||||||
|
|
||||||
backend.get_foo("a")
|
backend.get_foo("a")
|
||||||
|
@ -170,7 +170,8 @@ minetest.register_on_chat_message(function(name, message)
|
|||||||
elseif minetest.check_player_privs(name, { shout = true }) then
|
elseif minetest.check_player_privs(name, { shout = true }) then
|
||||||
print(name .. " said " .. message)
|
print(name .. " said " .. message)
|
||||||
else
|
else
|
||||||
print(name .. " tried to say " .. message .. " but doesn't have shout")
|
print(name .. " tried to say " .. message ..
|
||||||
|
" but doesn't have shout")
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
@ -150,7 +150,8 @@ ChatCmdBuilder.new("admin", function(cmd)
|
|||||||
local player = minetest.get_player_by_name(target)
|
local player = minetest.get_player_by_name(target)
|
||||||
if player then
|
if player then
|
||||||
player:setpos(pos)
|
player:setpos(pos)
|
||||||
return true, "Moved " .. target .. " to " .. minetest.pos_to_string(pos)
|
return true, "Moved " .. target .. " to " ..
|
||||||
|
minetest.pos_to_string(pos)
|
||||||
else
|
else
|
||||||
return false, "Unable to find " .. target
|
return false, "Unable to find " .. target
|
||||||
end
|
end
|
||||||
|
@ -147,7 +147,8 @@ minetest.register_chatcommand("formspec", {
|
|||||||
})
|
})
|
||||||
|
|
||||||
-- Register callback
|
-- Register callback
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player,
|
||||||
|
formname, fields)
|
||||||
if formname ~= "mymod:form" then
|
if formname ~= "mymod:form" then
|
||||||
-- Formname is not mymod:form,
|
-- Formname is not mymod:form,
|
||||||
-- exit callback.
|
-- exit callback.
|
||||||
@ -155,10 +156,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Send message to player.
|
-- Send message to player.
|
||||||
minetest.chat_send_player(player:get_player_name(), "You said: " .. fields.name .. "!")
|
minetest.chat_send_player(player:get_player_name(),
|
||||||
|
"You said: " .. fields.name .. "!")
|
||||||
|
|
||||||
-- Return true to stop other minetest.register_on_player_receive_fields
|
-- Return true to stop other callbacks from
|
||||||
-- from receiving this submission.
|
-- receiving this submission.
|
||||||
return true
|
return true
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
@ -213,7 +215,8 @@ local land_formspec_context = {}
|
|||||||
minetest.register_chatcommand("land", {
|
minetest.register_chatcommand("land", {
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
if param == "" then
|
if param == "" then
|
||||||
minetest.chat_send_player(name, "Incorrect parameters - supply a land ID")
|
minetest.chat_send_player(name,
|
||||||
|
"Incorrect parameters - supply a land ID")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -233,7 +236,8 @@ minetest.register_chatcommand("land", {
|
|||||||
--
|
--
|
||||||
-- Step 2) retrieve context when player submits the form
|
-- Step 2) retrieve context when player submits the form
|
||||||
--
|
--
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player,
|
||||||
|
formname, fields)
|
||||||
if formname ~= "mylandowner:edit" then
|
if formname ~= "mylandowner:edit" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
@ -128,9 +128,9 @@ player:hud_add({
|
|||||||
})
|
})
|
||||||
|
|
||||||
-- Get the dig and place count from storage, or default to 0
|
-- Get the dig and place count from storage, or default to 0
|
||||||
local digs = tonumber(player:get_attribute("scoreboard:digs") or 0)
|
local digs = tonumber(player:get_attribute("score:digs") or 0)
|
||||||
local digs_text = "Digs: " .. digs
|
local digs_text = "Digs: " .. digs
|
||||||
local places = tonumber(player:get_attribute("scoreboard:digs") or 0)
|
local places = tonumber(player:get_attribute("score:digs") or 0)
|
||||||
local places_text = "Places: " .. places
|
local places_text = "Places: " .. places
|
||||||
|
|
||||||
player:hud_add({
|
player:hud_add({
|
||||||
@ -172,7 +172,7 @@ player:hud_add({
|
|||||||
hud_elem_type = "image",
|
hud_elem_type = "image",
|
||||||
position = {x = 1, y = 0.5},
|
position = {x = 1, y = 0.5},
|
||||||
offset = {x = -220, y = 0},
|
offset = {x = -220, y = 0},
|
||||||
text = "scoreboard_background.png",
|
text = "score_background.png",
|
||||||
scale = { x = 1, y = 1},
|
scale = { x = 1, y = 1},
|
||||||
alignment = { x = 1, y = 0 },
|
alignment = { x = 1, y = 0 },
|
||||||
})
|
})
|
||||||
@ -200,13 +200,13 @@ For example, `x=-100` is 100% of the width.
|
|||||||
Let's make the progress bar for our score panel as an example of scale:
|
Let's make the progress bar for our score panel as an example of scale:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local percent = tonumber(player:get_attribute("scoreboard:score") or 0.2)
|
local percent = tonumber(player:get_attribute("score:score") or 0.2)
|
||||||
|
|
||||||
player:hud_add({
|
player:hud_add({
|
||||||
hud_elem_type = "image",
|
hud_elem_type = "image",
|
||||||
position = {x = 1, y = 0.5},
|
position = {x = 1, y = 0.5},
|
||||||
offset = {x = -215, y = 23},
|
offset = {x = -215, y = 23},
|
||||||
text = "scoreboard_bar_empty.png",
|
text = "score_bar_empty.png",
|
||||||
scale = { x = 1, y = 1},
|
scale = { x = 1, y = 1},
|
||||||
alignment = { x = 1, y = 0 },
|
alignment = { x = 1, y = 0 },
|
||||||
})
|
})
|
||||||
@ -215,7 +215,7 @@ player:hud_add({
|
|||||||
hud_elem_type = "image",
|
hud_elem_type = "image",
|
||||||
position = {x = 1, y = 0.5},
|
position = {x = 1, y = 0.5},
|
||||||
offset = {x = -215, y = 23},
|
offset = {x = -215, y = 23},
|
||||||
text = "scoreboard_bar_full.png",
|
text = "score_bar_full.png",
|
||||||
scale = { x = percent, y = 1},
|
scale = { x = percent, y = 1},
|
||||||
alignment = { x = 1, y = 0 },
|
alignment = { x = 1, y = 0 },
|
||||||
})
|
})
|
||||||
@ -255,18 +255,18 @@ local idx = player:hud_add({
|
|||||||
## Storing IDs
|
## Storing IDs
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
scoreboard = {}
|
score = {}
|
||||||
local saved_huds = {}
|
local saved_huds = {}
|
||||||
|
|
||||||
function scoreboard.update_hud(player)
|
function score.update_hud(player)
|
||||||
local player_name = player:get_player_name()
|
local player_name = player:get_player_name()
|
||||||
|
|
||||||
local digs = tonumber(player:get_attribute("scoreboard:digs") or 0)
|
local digs = tonumber(player:get_attribute("score:digs") or 0)
|
||||||
local digs_text = "Digs: " .. digs
|
local digs_text = "Digs: " .. digs
|
||||||
local places = tonumber(player:get_attribute("scoreboard:digs") or 0)
|
local places = tonumber(player:get_attribute("score:digs") or 0)
|
||||||
local places_text = "Places: " .. places
|
local places_text = "Places: " .. places
|
||||||
|
|
||||||
local percent = tonumber(player:get_attribute("scoreboard:score") or 0.2)
|
local percent = tonumber(player:get_attribute("score:score") or 0.2)
|
||||||
|
|
||||||
local ids = saved_huds[player_name]
|
local ids = saved_huds[player_name]
|
||||||
if ids then
|
if ids then
|
||||||
@ -282,7 +282,7 @@ function scoreboard.update_hud(player)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_joinplayer(scoreboard.update_hud)
|
minetest.register_on_joinplayer(score.update_hud)
|
||||||
|
|
||||||
minetest.register_on_leaveplayer(function(player)
|
minetest.register_on_leaveplayer(function(player)
|
||||||
saved_huds[player:get_player_name()] = nil
|
saved_huds[player:get_player_name()] = nil
|
||||||
|
@ -89,7 +89,8 @@ sfinv.register_page("myadmin:myadmin", {
|
|||||||
if not is_first then
|
if not is_first then
|
||||||
formspec[#formspec + 1] = ","
|
formspec[#formspec + 1] = ","
|
||||||
end
|
end
|
||||||
formspec[#formspec + 1] = minetest.formspec_escape(player_name)
|
formspec[#formspec + 1] =
|
||||||
|
minetest.formspec_escape(player_name)
|
||||||
is_first = false
|
is_first = false
|
||||||
end
|
end
|
||||||
formspec[#formspec + 1] = "]"
|
formspec[#formspec + 1] = "]"
|
||||||
@ -98,7 +99,8 @@ sfinv.register_page("myadmin:myadmin", {
|
|||||||
formspec[#formspec + 1] = "button[0.1,3.3;2,1;kick;Kick]"
|
formspec[#formspec + 1] = "button[0.1,3.3;2,1;kick;Kick]"
|
||||||
formspec[#formspec + 1] = "button[2.1,3.3;2,1;ban;Kick + Ban]"
|
formspec[#formspec + 1] = "button[2.1,3.3;2,1;ban;Kick + Ban]"
|
||||||
|
|
||||||
-- Wrap the formspec in sfinv's layout (ie: adds the tabs and background)
|
-- Wrap the formspec in sfinv's layout
|
||||||
|
-- (ie: adds the tabs and background)
|
||||||
return sfinv.make_formspec(player, context,
|
return sfinv.make_formspec(player, context,
|
||||||
table.concat(formspec, ""), false)
|
table.concat(formspec, ""), false)
|
||||||
end,
|
end,
|
||||||
@ -145,7 +147,8 @@ on_player_receive_fields = function(self, player, context, fields)
|
|||||||
|
|
||||||
-- Kick button was pressed
|
-- Kick button was pressed
|
||||||
elseif fields.kick then
|
elseif fields.kick then
|
||||||
local player_name = context.myadmin_players[context.myadmin_selected_idx]
|
local player_name =
|
||||||
|
context.myadmin_players[context.myadmin_selected_idx]
|
||||||
if player_name then
|
if player_name then
|
||||||
minetest.chat_send_player(player:get_player_name(),
|
minetest.chat_send_player(player:get_player_name(),
|
||||||
"Kicked " .. player_name)
|
"Kicked " .. player_name)
|
||||||
@ -154,7 +157,8 @@ on_player_receive_fields = function(self, player, context, fields)
|
|||||||
|
|
||||||
-- Ban button was pressed
|
-- Ban button was pressed
|
||||||
elseif fields.ban then
|
elseif fields.ban then
|
||||||
local player_name = context.myadmin_players[context.myadmin_selected_idx]
|
local player_name =
|
||||||
|
context.myadmin_players[context.myadmin_selected_idx]
|
||||||
if player_name then
|
if player_name then
|
||||||
minetest.chat_send_player(player:get_player_name(),
|
minetest.chat_send_player(player:get_player_name(),
|
||||||
"Banned " .. player_name)
|
"Banned " .. player_name)
|
||||||
@ -202,7 +206,8 @@ local function on_grant_revoke(grantee, granter, priv)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check that the function exists, in order to support older Minetest versions
|
-- Check that the function exists,
|
||||||
|
-- in order to support older Minetest versions
|
||||||
if minetest.register_on_priv_grant then
|
if minetest.register_on_priv_grant then
|
||||||
minetest.register_on_priv_grant(on_grant_revoke)
|
minetest.register_on_priv_grant(on_grant_revoke)
|
||||||
minetest.register_on_priv_revoke(on_grant_revoke)
|
minetest.register_on_priv_revoke(on_grant_revoke)
|
||||||
|
@ -104,7 +104,8 @@ acceptable.
|
|||||||
```lua
|
```lua
|
||||||
-- Controller
|
-- Controller
|
||||||
function land.handle_create_submit(name, area_name)
|
function land.handle_create_submit(name, area_name)
|
||||||
-- process stuff (ie: check for overlaps, check quotas, check permissions)
|
-- process stuff
|
||||||
|
-- (ie: check for overlaps, check quotas, check permissions)
|
||||||
|
|
||||||
land.create(name, area_name)
|
land.create(name, area_name)
|
||||||
end
|
end
|
||||||
@ -138,8 +139,10 @@ minetest.register_chatcommand("/land", {
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player,
|
||||||
land.handle_create_submit(player:get_player_name(), fields.area_name)
|
formname, fields)
|
||||||
|
land.handle_create_submit(player:get_player_name(),
|
||||||
|
fields.area_name)
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -235,7 +238,8 @@ Then the other code registers its interest:
|
|||||||
|
|
||||||
-- awards
|
-- awards
|
||||||
mobs.register_on_death(function(mob, reason)
|
mobs.register_on_death(function(mob, reason)
|
||||||
if reason.type == "punch" and reason.object and reason.object:is_player() then
|
if reason.type == "punch" and reason.object and
|
||||||
|
reason.object:is_player() then
|
||||||
awards.notify_mob_kill(reason.object, mob.name)
|
awards.notify_mob_kill(reason.object, mob.name)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
@ -34,7 +34,8 @@ minetest.register_on_joinplayer(function(player)
|
|||||||
foobar[player:get_player_name()] = player
|
foobar[player:get_player_name()] = player
|
||||||
-- RISKY
|
-- RISKY
|
||||||
-- It's recommended to just not do this
|
-- It's recommended to just not do this
|
||||||
-- use minetest.get_connected_players() and minetest.get_player_by_name() instead.
|
-- use minetest.get_connected_players() and
|
||||||
|
-- minetest.get_player_by_name() instead.
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -80,7 +81,8 @@ local function show_formspec(name)
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player,
|
||||||
|
formname, fields)
|
||||||
-- BAD! Missing privilege check here!
|
-- BAD! Missing privilege check here!
|
||||||
|
|
||||||
local privs = minetest.get_player_privs(fields.target)
|
local privs = minetest.get_player_privs(fields.target)
|
||||||
@ -94,7 +96,8 @@ end)
|
|||||||
Instead, do this:
|
Instead, do this:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player,
|
||||||
|
formname, fields)
|
||||||
if not minetest.check_player_privs(name, { privs = true }) then
|
if not minetest.check_player_privs(name, { privs = true }) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@ -136,9 +139,11 @@ it will only be saved in the engine if the callback caller sets it.
|
|||||||
Avoid this:
|
Avoid this:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing)
|
minetest.register_on_item_eat(function(hp_change, replace_with_item,
|
||||||
|
itemstack, user, pointed_thing)
|
||||||
itemstack:get_meta():set_string("description", "Partially eaten")
|
itemstack:get_meta():set_string("description", "Partially eaten")
|
||||||
-- Almost correct! Data will be lost if another callback cancels the behaviour
|
-- Almost correct! Data will be lost if another
|
||||||
|
-- callback cancels the behaviour
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -146,9 +151,11 @@ If no callbacks cancel, then the stack will be set and the description will be u
|
|||||||
If a callback cancels, then the update may be lost. It's better to do this instead:
|
If a callback cancels, then the update may be lost. It's better to do this instead:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing)
|
minetest.register_on_item_eat(function(hp_change, replace_with_item,
|
||||||
|
itemstack, user, pointed_thing)
|
||||||
itemstack:get_meta():set_string("description", "Partially eaten")
|
itemstack:get_meta():set_string("description", "Partially eaten")
|
||||||
user:get_inventory():set_stack("main", user:get_wield_index(), itemstack)
|
user:get_inventory():set_stack("main", user:get_wield_index(),
|
||||||
|
itemstack)
|
||||||
-- Correct, description will always be set!
|
-- Correct, description will always be set!
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
@ -44,32 +44,6 @@ You license your code under LGPL 2.1 and your art under CC-BY-SA. This means:
|
|||||||
* If someone modifies your mod, they must give their version the same license.
|
* If someone modifies your mod, they must give their version the same license.
|
||||||
* Your copyright notice must be kept.
|
* Your copyright notice must be kept.
|
||||||
|
|
||||||
Add this copyright notice to your README.txt, or as a new file called LICENSE.txt:
|
|
||||||
|
|
||||||
License for Code
|
|
||||||
----------------
|
|
||||||
|
|
||||||
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 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.
|
|
||||||
|
|
||||||
License for Textures, Models and Sounds
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
CC-BY-SA 3.0 UNPORTED. Created by Your Name
|
|
||||||
|
|
||||||
### WTFPL or CC0
|
### WTFPL or CC0
|
||||||
|
|
||||||
These licenses allows anyone to do what they want with your mod.
|
These licenses allows anyone to do what they want with your mod.
|
||||||
@ -85,29 +59,6 @@ This is a common license for mod code. The only restriction it places on users
|
|||||||
of your mod is that they must include the same copyright notice and license
|
of your mod is that they must include the same copyright notice and license
|
||||||
in any copies of the mod or of substantial parts of the mod.
|
in any copies of the mod or of substantial parts of the mod.
|
||||||
|
|
||||||
To use this license, include the following in your readme or license file:
|
|
||||||
|
|
||||||
Copyright (c) <year> <your name> <emailaddress>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
## Packaging
|
## Packaging
|
||||||
|
|
||||||
There are some files that we recommend you include in your mod
|
There are some files that we recommend you include in your mod
|
||||||
@ -133,7 +84,7 @@ It should be short because it will be displayed in the content installer.
|
|||||||
|
|
||||||
Good example:
|
Good example:
|
||||||
|
|
||||||
Adds soup, cakes, bakes and juices. The food mod which supports the most ingredients.
|
Adds soup, cakes, bakes and juices
|
||||||
|
|
||||||
Don't do this:
|
Don't do this:
|
||||||
|
|
||||||
|
@ -41,7 +41,8 @@ Any users can submit almost any formspec with any values at any time.
|
|||||||
Here's some real code found in a mod:
|
Here's some real code found in a mod:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player,
|
||||||
|
formname, fields)
|
||||||
-- Todo: fix security issue here
|
-- Todo: fix security issue here
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
if formname ~= "mymod:fs" then
|
if formname ~= "mymod:fs" then
|
||||||
@ -49,9 +50,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
end
|
end
|
||||||
|
|
||||||
for key, field in pairs(fields) do
|
for key, field in pairs(fields) do
|
||||||
local x,y,z = string.match(key, "goto_([%d-]+)_([%d-]+)_([%d-]+)")
|
local x,y,z = string.match(key,
|
||||||
|
"goto_([%d-]+)_([%d-]+)_([%d-]+)")
|
||||||
if x and y and z then
|
if x and y and z then
|
||||||
player:setpos({ x=tonumber(x), y=tonumber(y), z=tonumber(z) })
|
player:set_pos({ x=tonumber(x), y=tonumber(y),
|
||||||
|
z=tonumber(z) })
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -144,7 +144,8 @@ describe("list_areas", function()
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- The above two tests are actually pointless, as this one tests both things
|
-- The above two tests are actually pointless,
|
||||||
|
-- as this one tests both things
|
||||||
it("returns correct thing", function()
|
it("returns correct thing", function()
|
||||||
chat_send_all_calls = {} -- reset table
|
chat_send_all_calls = {} -- reset table
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user