This Final Minetest commit includes ports of the following Troll- test commits plus additional changes. The changes are related to MT Lua C++ to interface code, the MT Lua API, and MT CSM (Client- Side Modding). Desc: Fix "add_entity" returning unusable reference Commit:masterf6f6dd140f
From: sfan5 <sfan5@live.de> Date: Sun, 26 Apr 2020 20:29:16 +0200 Desc: [CSM] Fix and improve "minetest.get_language()" Commit:c44318a253
From: sfan5 <sfan5@live.de> Date: Sat Nov 9 16:15:05 2019 +0100 Desc: [CSM] Expose more env functions Commit:b57dc70769
From: sfan5 <sfan5@live.de> Date: Sat, 9 Nov 2019 00:22:42 +0100 Desc: Introduce "get_modpath()" for CSM Commit:b1f2a69382
From: sfan5 <sfan5@live.de> Date: Fri Nov 8 20:18:41 2019 +0100 Desc: Modernize Lua read part 2 of 2 (#7410) Commit:eef62c82a2
From: Loic Blot <nerzhul@users.noreply.github.com> Date: Sat, 30 Jun 2018 17:11:38 +0200 Desc: Modernize Lua read part 1 of 2 (#7394) Commit:180e551c56
From: Loic Blot <nerzhul@users.noreply.github.com> Date: Mon, 4 Jun 2018 22:38:07 +0200 Related technical notes: 1. To enable CSM, users need to add the following setting to "minetest.conf" on the client side: enable_client_modding = false 2. Additionally, to load the sample CSM mod provided, users need to edit "clientmods/mods.conf" on the client side and set "load_ mod_previw" to true: load_mod_preview = true
@@ -294,6 +294,7 @@ LOCAL_SRC_FILES += \ | |||
jni/src/script/common/c_converter.cpp \ | |||
jni/src/script/common/c_internal.cpp \ | |||
jni/src/script/common/c_types.cpp \ | |||
jni/src/script/common/helper.cpp \ | |||
jni/src/script/cpp_api/s_async.cpp \ | |||
jni/src/script/cpp_api/s_base.cpp \ | |||
jni/src/script/cpp_api/s_client.cpp \ | |||
@@ -0,0 +1,16 @@ | |||
-- CSM death formspec. Only used when clientside modding is enabled, otherwise | |||
-- handled by the engine. | |||
core.register_on_death(function() | |||
core.display_chat_message("You died.") | |||
local formspec = "size[11,5.5]bgcolor[#320000b4;true]" .. | |||
"label[4.85,1.35;" .. fgettext("You died") .. | |||
"]button_exit[4,3;3,0.5;btn_respawn;".. fgettext("Respawn") .."]" | |||
core.show_formspec("bultin:death", formspec) | |||
end) | |||
core.register_on_formspec_input(function(formname, fields) | |||
if formname == "bultin:death" then | |||
core.send_respawn() | |||
end | |||
end) |
@@ -0,0 +1 @@ | |||
load_mod_preview = false |
@@ -1,2 +1,2 @@ | |||
print("Loaded example file!, loading more examples") | |||
dofile("preview:examples/first.lua") | |||
dofile (core.get_modpath (core.get_current_modname()) | |||
.. "examples/first.lua") |
@@ -1 +1 @@ | |||
print("loaded first.lua example file") | |||
print ("Loaded first.lua example file") |
@@ -1,173 +1,231 @@ | |||
local modname = core.get_current_modname() or "??" | |||
-- =================================================================== | |||
local modname = assert (core.get_current_modname()) | |||
local modstorage = core.get_mod_storage() | |||
local mod_channel | |||
dofile("preview:example.lua") | |||
core.register_on_shutdown(function() | |||
print("[PREVIEW] shutdown client") | |||
end) | |||
local id = nil | |||
-- =================================================================== | |||
local server_info = core.get_server_info() | |||
print("Server version: " .. server_info.protocol_version) | |||
print("Server ip: " .. server_info.ip) | |||
print("Server address: " .. server_info.address) | |||
print("Server port: " .. server_info.port) | |||
dofile (core.get_modpath (modname) .. "example.lua") | |||
core.register_on_inventory_open(function(inventory) | |||
print("INVENTORY OPEN") | |||
print(dump(inventory)) | |||
return false | |||
end) | |||
-- =================================================================== | |||
core.register_on_placenode(function(pointed_thing, node) | |||
print("The local player place a node!") | |||
print("pointed_thing :" .. dump(pointed_thing)) | |||
print("node placed :" .. dump(node)) | |||
return false | |||
core.register_on_shutdown (function() | |||
print ("[Preview] shutdown client") | |||
end) | |||
core.register_on_item_use(function(itemstack, pointed_thing) | |||
print("The local player used an item!") | |||
print("pointed_thing :" .. dump(pointed_thing)) | |||
print("item = " .. itemstack:get_name()) | |||
return false | |||
end) | |||
-- =================================================================== | |||
do | |||
local server_info = core.get_server_info() | |||
print ("Server version: " .. server_info.protocol_version) | |||
print ("Server ip: " .. server_info.ip) | |||
print ("Server address: " .. server_info.address) | |||
print ("Server port: " .. server_info.port) | |||
local l1, l2 = core.get_language() | |||
print ("Configured language: " .. l1 .. " / " .. l2) | |||
end | |||
core.register_on_receiving_chat_message(function(message) | |||
print("[PREVIEW] Received message " .. message) | |||
-- =================================================================== | |||
if false then | |||
core.register_on_inventory_open (function (inventory) | |||
print ("Inventory open") | |||
print (dump (inventory)) | |||
return false | |||
end) | |||
end | |||
-- =================================================================== | |||
core.register_on_placenode (function (pointed_thing, node) | |||
print ("The local player placed a node") | |||
print ("pointed_thing :" .. dump (pointed_thing )) | |||
print ("node placed :" .. dump (node )) | |||
return false | |||
end) | |||
core.register_on_sending_chat_message(function(message) | |||
print("[PREVIEW] Sending message " .. message) | |||
-- =================================================================== | |||
core.register_on_item_use (function (itemstack, pointed_thing) | |||
print ("The local player used an item") | |||
print ("pointed_thing :" .. dump (pointed_thing)) | |||
print ("item = " .. itemstack:get_name()) | |||
return false | |||
end) | |||
core.register_on_hp_modification(function(hp) | |||
print("[PREVIEW] HP modified " .. hp) | |||
end) | |||
-- =================================================================== | |||
core.register_on_damage_taken(function(hp) | |||
print("[PREVIEW] Damage taken " .. hp) | |||
end) | |||
-- This setting should usually be false as it enables debug code that | |||
-- is high-load and/or verbose. | |||
core.register_globalstep(function(dtime) | |||
-- print("[PREVIEW] globalstep " .. dtime) | |||
end) | |||
local high_debug = false | |||
core.register_chatcommand("dump", { | |||
func = function(param) | |||
return true, dump(_G) | |||
end, | |||
}) | |||
if high_debug then | |||
core.register_on_receiving_chat_message (function (message) | |||
print ("[Preview] Received message " .. message) | |||
return false | |||
end) | |||
core.register_on_sending_chat_message (function (message) | |||
print ("[Preview] Sending message " .. message) | |||
return false | |||
end) | |||
core.register_chatcommand("colorize_test", { | |||
func = function(param) | |||
return true, core.colorize("red", param) | |||
core.register_on_hp_modification (function (hp) | |||
print ("[Preview] HP modified " .. hp) | |||
end) | |||
core.register_on_damage_taken (function (hp) | |||
print ("[Preview] Damage taken " .. hp) | |||
end) | |||
core.register_globalstep (function (dtime) | |||
-- print ("[Preview] globalstep " .. dtime) | |||
end) | |||
core.register_chatcommand ("dump", { | |||
func = function (param) | |||
return true, dump(_G) | |||
end, | |||
}) | |||
end | |||
-- =================================================================== | |||
core.register_chatcommand ("colorize_test", { | |||
func = function (param) | |||
return true, core.colorize ("red", param) | |||
end, | |||
}) | |||
core.register_chatcommand("test_node", { | |||
func = function(param) | |||
core.display_chat_message(dump(core.get_node({x=0, y=0, z=0}))) | |||
core.display_chat_message(dump(core.get_node_or_nil({x=0, y=0, z=0}))) | |||
-- =================================================================== | |||
core.register_chatcommand ("test_node", { | |||
func = function (param) | |||
core.display_chat_message (dump (core.get_node ({ | |||
x=0, y=0, z=0 }))) | |||
core.display_chat_message (dump (core.get_node_or_nil ({ | |||
x=0, y=0, z=0 }))) | |||
end, | |||
}) | |||
-- =================================================================== | |||
local function preview_minimap() | |||
local minimap = core.ui.minimap | |||
if not minimap then | |||
print("[PREVIEW] Minimap is disabled. Skipping.") | |||
print ("[Preview] Minimap is disabled. Skipping.") | |||
return | |||
end | |||
minimap:set_mode(4) | |||
minimap:show() | |||
minimap:set_pos({x=5, y=50, z=5}) | |||
minimap:set_shape(math.random(0, 1)) | |||
print("[PREVIEW] Minimap: mode => " .. dump(minimap:get_mode()) .. | |||
print ("[Preview] Minimap: mode => " .. dump(minimap:get_mode()) .. | |||
" position => " .. dump(minimap:get_pos()) .. | |||
" angle => " .. dump(minimap:get_angle())) | |||
end | |||
-- =================================================================== | |||
core.after(2, function() | |||
print("[PREVIEW] loaded " .. modname .. " mod") | |||
modstorage:set_string("current_mod", modname) | |||
print(modstorage:get_string("current_mod")) | |||
print ("[Preview] loaded " .. modname .. " mod") | |||
modstorage:set_string ("current_mod", modname) | |||
print (modstorage:get_string ("current_mod")) | |||
preview_minimap() | |||
end) | |||
-- =================================================================== | |||
core.after(5, function() | |||
if core.ui.minimap then | |||
if core.ui.minimap then | |||
core.ui.minimap:show() | |||
end | |||
print("[PREVIEW] Day count: " .. core.get_day_count() .. | |||
print ("[Preview] Day count: " .. | |||
core.get_day_count() .. | |||
" time of day " .. core.get_timeofday()) | |||
print("[PREVIEW] Node level: " .. core.get_node_level({x=0, y=20, z=0}) .. | |||
" max level " .. core.get_node_max_level({x=0, y=20, z=0})) | |||
print ("[Preview] Node level: " .. | |||
core.get_node_level({x=0, y=20, z=0}) .. | |||
" max level " .. core.get_node_max_level ({x=0, y=20, z=0})) | |||
print("[PREVIEW] Find node near: " .. dump(core.find_node_near({x=0, y=20, z=0}, 10, | |||
print ("[Preview] Find node near: " .. | |||
dump (core.find_node_near ({x=0, y=20, z=0}, 10, | |||
{"group:tree", "default:dirt", "default:stone"}))) | |||
end) | |||
core.register_on_dignode(function(pos, node) | |||
print("The local player dug a node!") | |||
print("pos:" .. dump(pos)) | |||
print("node:" .. dump(node)) | |||
-- =================================================================== | |||
core.register_on_dignode (function (pos, node) | |||
print ("The local player dug a node") | |||
print ("pos:" .. dump (pos )) | |||
print ("node:" .. dump (node )) | |||
return false | |||
end) | |||
core.register_on_punchnode(function(pos, node) | |||
print("The local player punched a node!") | |||
-- =================================================================== | |||
core.register_on_punchnode (function (pos, node) | |||
print ("The local player punched a node") | |||
local itemstack = core.get_wielded_item() | |||
--[[ | |||
--[[ | |||
-- getters | |||
print(dump(itemstack:is_empty())) | |||
print(dump(itemstack:get_name())) | |||
print(dump(itemstack:get_count())) | |||
print(dump(itemstack:get_wear())) | |||
print(dump(itemstack:get_meta())) | |||
print(dump(itemstack:get_metadata() | |||
print(dump(itemstack:is_known())) | |||
--print(dump(itemstack:get_definition())) | |||
print(dump(itemstack:get_tool_capabilities())) | |||
print(dump(itemstack:to_string())) | |||
print(dump(itemstack:to_table())) | |||
print (dump(itemstack:is_empty())) | |||
print (dump(itemstack:get_name())) | |||
print (dump(itemstack:get_count())) | |||
print (dump(itemstack:get_wear())) | |||
print (dump(itemstack:get_meta())) | |||
print (dump(itemstack:get_metadata() | |||
print (dump(itemstack:is_known())) | |||
--print (dump(itemstack:get_definition())) | |||
print (dump(itemstack:get_tool_capabilities())) | |||
print (dump(itemstack:to_string())) | |||
print (dump(itemstack:to_table())) | |||
-- setters | |||
print(dump(itemstack:set_name("default:dirt"))) | |||
print(dump(itemstack:set_count("95"))) | |||
print(dump(itemstack:set_wear(934))) | |||
print(dump(itemstack:get_meta())) | |||
print(dump(itemstack:get_metadata())) | |||
--]] | |||
print(dump(itemstack:to_table())) | |||
print("pos:" .. dump(pos)) | |||
print("node:" .. dump(node)) | |||
print (dump(itemstack:set_name("default:dirt"))) | |||
print (dump(itemstack:set_count("95"))) | |||
print (dump(itemstack:set_wear(934))) | |||
print (dump(itemstack:get_meta())) | |||
print (dump(itemstack:get_metadata())) | |||
--]] | |||
print (dump (itemstack:to_table())) | |||
print ("pos:" .. dump (pos )) | |||
print ("node:" .. dump (node )) | |||
return false | |||
end) | |||
core.register_chatcommand("privs", { | |||
func = function(param) | |||
return true, core.privs_to_string(minetest.get_privilege_list()) | |||
-- =================================================================== | |||
core.register_chatcommand ("privs", { | |||
func = function (param) | |||
return true, core.privs_to_string (minetest.get_privilege_list()) | |||
end, | |||
}) | |||
core.register_chatcommand("text", { | |||
func = function(param) | |||
return core.localplayer:hud_change(id, "text", param) | |||
-- =================================================================== | |||
local id = nil | |||
core.register_chatcommand ("text", { | |||
func = function (param) | |||
return core.localplayer:hud_change (id, "text", param) | |||
end, | |||
}) | |||
core.register_on_mods_loaded(function() | |||
core.log("Yeah preview mod is loaded with other CSM mods.") | |||
-- =================================================================== | |||
core.register_on_mods_loaded (function() | |||
core.log ("CSM preview mod is loaded") | |||
end) | |||
-- =================================================================== | |||
-- End of file. |
@@ -20,7 +20,7 @@ scripting in run-time loaded mods. | |||
A mod is a self-contained bunch of scripts, textures and other things | |||
that are loaded by and interface with Minetest. | |||
Transferirng client-sided mods form the server to the client is planned, but not implemented yet. | |||
Transferring client-sided mods form the server to the client is planned, but not implemented yet. | |||
If you see a deficiency in the API, feel free to attempt to add the | |||
functionality in the engine and API. You can send such improvements as | |||
@@ -625,8 +625,19 @@ Minetest namespace reference | |||
### Utilities | |||
* `minetest.get_current_modname()`: returns the currently loading mod's name, when we are loading a mod | |||
* `minetest.get_language()`: returns the currently set gettext language. | |||
* `minetest.get_current_modname()`: returns the currently loading | |||
mod's name, when we are loading a mod | |||
* `minetest.get_modpath(modname)`: returns virtual path of given mod | |||
including the trailing separator. This is useful to load additional | |||
Lua files contained in your mod: | |||
e.g. `dofile(minetest.get_modpath(minetest.get_current_modname()) .. "stuff.lua")` | |||
* `minetest.get_language()`: returns two strings | |||
* the current gettext locale | |||
* the current language code (the same as used for client-side | |||
translations) | |||
* `minetest.get_version()`: returns a table containing components of the | |||
engine version. Components: | |||
* `project`: Name of the project, eg, "Minetest" | |||
@@ -713,15 +724,57 @@ Call these functions only at load time! | |||
* Returns the time of day: `0` for midnight, `0.5` for midday | |||
### Map | |||
* `minetest.get_node_or_nil(pos)` | |||
* `minetest.get_node_or_nil (pos)` | |||
* Returns the node at the given position as table in the format | |||
`{name="node_name", param1=0, param2=0}`, returns `nil` | |||
for unloaded areas or flavour limited areas. | |||
* `minetest.find_node_near(pos, radius, nodenames, [search_center])`: returns pos or `nil` | |||
* `minetest.get_node_light (pos, timeofday)` | |||
* Gets the light value at the given position. Note that the light value | |||
"inside" the node at the given position is returned, so you usually want | |||
to get the light value of a neighbor. | |||
* `pos`: The position where to measure the light. | |||
* `timeofday`: `nil` for current time, `0` for night, `0.5` for day | |||
* Returns a number between `0` and `15` or `nil` | |||
* `minetest.find_node_near (pos, radius, nodenames, [search_center])`: returns pos or `nil` | |||
* `radius`: using a maximum metric | |||
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"` | |||
* `search_center` is an optional boolean (default: `false`) | |||
If true `pos` is also checked for the nodes | |||
* `minetest.find_nodes_in_area (pos1, pos2, nodenames)`: returns a list of | |||
positions. | |||
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"` | |||
* First return value: Table with all node positions | |||
* Second return value: Table with the count of each node with the node name | |||
as index. | |||
* Area volume is limited to 4,096,000 nodes | |||
* `minetest.find_nodes_in_area_under_air (pos1, pos2, nodenames)`: returns a | |||
list of positions. | |||
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"` | |||
* Return value: Table with all node positions with a node air above | |||
* Area volume is limited to 4,096,000 nodes | |||
* `minetest.line_of_sight (pos1, pos2)`: returns `boolean, pos` | |||
* Checks if there is anything other than air between pos1 and pos2. | |||
* Returns false if something is blocking the sight. | |||
* Returns the position of the blocking node when `false` | |||
* `pos1`: First position | |||
* `pos2`: Second position | |||
* `minetest.raycast (pos1, pos2, objects, liquids)`: returns `Raycast` | |||
* Creates a `Raycast` object. | |||
* `pos1`: start of the ray | |||
* `pos2`: end of the ray | |||
* `objects`: if false, only nodes will be returned. Default is `true`. | |||
* `liquids`: if false, liquid nodes won't be returned. Default is `false`. | |||
* `minetest.find_nodes_with_meta(pos1, pos2)` | |||
* Get a table of positions of nodes that have metadata within a region | |||
{pos1, pos2}. | |||
* `minetest.get_meta(pos)` | |||
* Get a `NodeMetaRef` at that position | |||
* `minetest.get_node_level(pos)` | |||
@@ -1003,6 +1056,32 @@ Can be obtained via `minetest.get_meta(pos)`. | |||
* `fields`: key-value storage | |||
* `inventory`: `{list1 = {}, ...}}` | |||
### `Raycast` | |||
A raycast on the map. It works with selection boxes. | |||
Can be used as an iterator in a for loop as: | |||
local ray = Raycast(...) | |||
for pointed_thing in ray do | |||
... | |||
end | |||
The map is loaded as the ray advances. If the map is modified after the | |||
`Raycast` is created, the changes may or may not have an effect on the object. | |||
It can be created via `Raycast(pos1, pos2, objects, liquids)` or | |||
`minetest.raycast(pos1, pos2, objects, liquids)` where: | |||
* `pos1`: start of the ray | |||
* `pos2`: end of the ray | |||
* `objects`: if false, only nodes will be returned. Default is true. | |||
* `liquids`: if false, liquid nodes won't be returned. Default is false. | |||
#### Methods | |||
* `next()`: returns a `pointed_thing` with exact pointing location | |||
* Returns the next thing pointed by the ray or nil. | |||
----------------- | |||
### Definitions | |||
* `minetest.get_node_def(nodename)` | |||
@@ -1355,6 +1355,11 @@ MapNode Client::getNode(v3s16 p, bool *is_valid_position) | |||
return m_env.getMap().getNodeNoEx(p, is_valid_position); | |||
} | |||
v3s16 Client::CSMClampPos(v3s16 pos) | |||
{ | |||
return pos; | |||
} | |||
void Client::addNode(v3s16 p, MapNode n, bool remove_metadata) | |||
{ | |||
//TimeTaker timer1("Client::addNode()"); | |||
@@ -380,6 +380,7 @@ public: | |||
* @return | |||
*/ | |||
MapNode getNode(v3s16 p, bool *is_valid_position); | |||
v3s16 CSMClampPos (v3s16 pos); | |||
void addNode(v3s16 p, MapNode n, bool remove_metadata = true); | |||
void setPlayerControl(PlayerControl &control); | |||
@@ -2289,19 +2289,28 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase, | |||
video::IVideoDriver* driver = Environment->getVideoDriver(); | |||
Inventory *inv = m_invmgr->getInventory(s.inventoryloc); | |||
if(!inv){ | |||
if (!inv) | |||
{ | |||
#ifdef NOTDEF // Prevent message flood | |||
warningstream<<"GUIFormSpecMenu::drawList(): " | |||
<<"The inventory location " | |||
<<"\""<<s.inventoryloc.dump()<<"\" doesn't exist" | |||
<<std::endl; | |||
#endif | |||
return; | |||
} | |||
InventoryList *ilist = inv->getList(s.listname); | |||
if(!ilist){ | |||
InventoryList *ilist = inv->getList (s.listname); | |||
if (!ilist) | |||
{ | |||
#ifdef NOTDEF // Prevent message flood | |||
warningstream<<"GUIFormSpecMenu::drawList(): " | |||
<<"The inventory list \""<<s.listname<<"\" @ \"" | |||
<<s.inventoryloc.dump()<<"\" doesn't exist" | |||
<<std::endl; | |||
#endif | |||
return; | |||
} | |||
@@ -3693,14 +3702,14 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) | |||
m_invmgr->inventoryAction(a); | |||
} else if (craft_amount > 0) { | |||
assert(s.isValid()); | |||
// if there are no items selected or the selected item | |||
// belongs to craftresult list, proceed with crafting | |||
if (m_selected_item == NULL || | |||
!m_selected_item->isValid() || m_selected_item->listname == "craftresult") { | |||
m_selected_content_guess = ItemStack(); // Clear | |||
assert(inv_s); | |||
// Send IACTION_CRAFT | |||
@@ -3,6 +3,7 @@ set(common_SCRIPT_COMMON_SRCS | |||
${CMAKE_CURRENT_SOURCE_DIR}/c_converter.cpp | |||
${CMAKE_CURRENT_SOURCE_DIR}/c_types.cpp | |||
${CMAKE_CURRENT_SOURCE_DIR}/c_internal.cpp | |||
${CMAKE_CURRENT_SOURCE_DIR}/helper.cpp | |||
PARENT_SCOPE) | |||
set(client_SCRIPT_COMMON_SRCS | |||
@@ -96,11 +96,10 @@ enum RunCallbacksMode | |||
// after seeing the first true value | |||
RUN_CALLBACKS_MODE_OR_SC, | |||
// Note: "a true value" and "a false value" refer to values that | |||
// are converted by lua_toboolean to true or false, respectively. | |||
// are converted by readParam<bool> to true or false, respectively. | |||
}; | |||
std::string script_get_backtrace(lua_State *L); | |||
int script_error_handler(lua_State *L); | |||
int script_exception_wrapper(lua_State *L, lua_CFunction f); | |||
void script_error(lua_State *L, int pcall_result, const char *mod, const char *fxn); | |||
void script_run_callbacks_f(lua_State *L, int nargs, | |||
@@ -0,0 +1,73 @@ | |||
/* | |||
Minetest | |||
Copyright (C) 2018 nerzhul, Loic Blot <loic.blot@unix-experience.fr> | |||
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. | |||
*/ | |||
#include "helper.h" | |||
#include <cmath> | |||
#include <sstream> | |||
#include "c_types.h" | |||
bool LuaHelper::isNaN(lua_State *L, int idx) | |||
{ | |||
return lua_type(L, idx) == LUA_TNUMBER && std::isnan(lua_tonumber(L, idx)); | |||
} | |||
/* | |||
* Read template functions | |||
*/ | |||
template <> bool LuaHelper::readParam(lua_State *L, int index) | |||
{ | |||
return lua_toboolean(L, index) != 0; | |||
} | |||
template <> bool LuaHelper::readParam(lua_State *L, int index, const bool &default_value) | |||
{ | |||
if (lua_isnil(L, index)) | |||
return default_value; | |||
return lua_toboolean(L, index) != 0; | |||
} | |||
template <> float LuaHelper::readParam(lua_State *L, int index) | |||
{ | |||
if (isNaN(L, index)) | |||
throw LuaError("NaN value is not allowed."); | |||
return (float)luaL_checknumber(L, index); | |||
} | |||
template <> std::string LuaHelper::readParam(lua_State *L, int index) | |||
{ | |||
std::string result; | |||
const char *str = luaL_checkstring(L, index); | |||
result.append(str); | |||
return result; | |||
} | |||
template <> | |||
std::string LuaHelper::readParam( | |||
lua_State *L, int index, const std::string &default_value) | |||
{ | |||
std::string result; | |||
const char *str = lua_tostring(L, index); | |||
if (str) | |||
result.append(str); | |||
else | |||
result = default_value; | |||
return result; | |||
} |
@@ -0,0 +1,54 @@ | |||
/* | |||
Minetest | |||
Copyright (C) 2018 nerzhul, Loic Blot <loic.blot@unix-experience.fr> | |||
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. | |||
*/ | |||
#pragma once | |||
extern "C" { | |||
#include <lua.h> | |||
#include <lauxlib.h> | |||
} | |||
class LuaHelper | |||
{ | |||
protected: | |||
static bool isNaN(lua_State *L, int idx); | |||
/** | |||
* Read a value using a template type T from Lua State L and index | |||
* | |||
* | |||
* @tparam T type to read from Lua | |||
* @param L Lua state | |||
* @param index Lua Index to read | |||
* @return read value from Lua | |||
*/ | |||
template <typename T> static T readParam(lua_State *L, int index); | |||
/** | |||
* Read a value using a template type T from Lua State L and index | |||
* | |||
* @tparam T type to read from Lua | |||
* @param L Lua state | |||
* @param index Lua Index to read | |||
* @param default_value default value to apply if nil | |||
* @return read value from Lua or default value if nil | |||
*/ | |||
template <typename T> | |||
static T readParam(lua_State *L, int index, const T &default_value); | |||
}; |
@@ -123,7 +123,7 @@ int ScriptApiBase::luaPanic(lua_State *L) | |||
{ | |||
std::ostringstream oss; | |||
oss << "LUA PANIC: unprotected error in call to Lua API (" | |||
<< lua_tostring(L, -1) << ")"; | |||
<< readParam<std::string>(L, -1) << ")"; | |||
FATAL_ERROR(oss.str().c_str()); | |||
// NOTREACHED | |||
return 0; | |||
@@ -153,7 +153,7 @@ void ScriptApiBase::loadScript(const std::string &script_path) | |||
} | |||
ok = ok && !lua_pcall(L, 0, 0, error_handler); | |||
if (!ok) { | |||
std::string error_msg = lua_tostring(L, -1); | |||
std::string error_msg = readParam<std::string>(L, -1); | |||
lua_pop(L, 2); // Pop error message and error handler | |||
throw ModError("Failed to load and run script from " + | |||
script_path + ":\n" + error_msg); | |||
@@ -255,10 +255,10 @@ void ScriptApiBase::stackDump(std::ostream &o) | |||
int t = lua_type(m_luastack, i); | |||
switch (t) { | |||
case LUA_TSTRING: /* strings */ | |||
o << "\"" << lua_tostring(m_luastack, i) << "\""; | |||
o << "\"" << readParam<std::string>(m_luastack, i) << "\""; | |||
break; | |||
case LUA_TBOOLEAN: /* booleans */ | |||
o << (lua_toboolean(m_luastack, i) ? "true" : "false"); | |||
o << (readParam<bool>(m_luastack, i) ? "true" : "false"); | |||
break; | |||
case LUA_TNUMBER: /* numbers */ { | |||
char buf[10]; | |||
@@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc., | |||
#include <string> | |||
#include <thread> | |||
#include <mutex> | |||
#include "common/helper.h" | |||
#include "util/basic_macros.h" | |||
extern "C" { | |||
@@ -70,7 +72,7 @@ class GUIEngine; | |||
class ServerActiveObject; | |||
class PlayerHPChangeReason; | |||
class ScriptApiBase { | |||
class ScriptApiBase : protected LuaHelper { | |||
public: | |||
ScriptApiBase(); | |||
virtual ~ScriptApiBase(); | |||
@@ -57,8 +57,7 @@ bool ScriptApiClient::on_sending_message(const std::string &message) | |||
// Call callbacks | |||
lua_pushstring(L, message.c_str()); | |||
runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC); | |||
bool ate = lua_toboolean(L, -1); | |||
return ate; | |||
return readParam<bool>(L, -1); | |||
} | |||
bool ScriptApiClient::on_receiving_message(const std::string &message) | |||
@@ -71,8 +70,7 @@ bool ScriptApiClient::on_receiving_message(const std::string &message) | |||
// Call callbacks | |||
lua_pushstring(L, message.c_str()); | |||
runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC); | |||
bool ate = lua_toboolean(L, -1); | |||
return ate; | |||
return readParam<bool>(L, -1); | |||
} | |||
void ScriptApiClient::on_damage_taken(int32_t damage_amount) | |||
@@ -186,8 +184,7 @@ bool ScriptApiClient::on_punchnode(v3s16 p, MapNode node) | |||
// Call functions | |||
runCallbacks(2, RUN_CALLBACKS_MODE_OR); | |||
bool blocked = lua_toboolean(L, -1); | |||
return blocked; | |||
return readParam<bool>(L, -1); | |||
} | |||
bool ScriptApiClient::on_placenode(const PointedThing &pointed, const ItemDefinition &item) | |||
@@ -204,7 +201,7 @@ bool ScriptApiClient::on_placenode(const PointedThing &pointed, const ItemDefini | |||
// Call functions | |||
runCallbacks(2, RUN_CALLBACKS_MODE_OR); | |||
return lua_toboolean(L, -1); | |||
return readParam<bool>(L, -1); | |||
} | |||
bool ScriptApiClient::on_item_use(const ItemStack &item, const PointedThing &pointed) | |||
@@ -221,7 +218,7 @@ bool ScriptApiClient::on_item_use(const ItemStack &item, const PointedThing &poi | |||
// Call functions | |||
runCallbacks(2, RUN_CALLBACKS_MODE_OR); | |||
return lua_toboolean(L, -1); | |||
return readParam<bool>(L, -1); | |||
} | |||
void ScriptApiClient::setEnv(ClientEnvironment *env) | |||
@@ -257,7 +257,7 @@ bool ScriptApiEntity::luaentity_Punch(u16 id, | |||
setOriginFromTable(object); | |||
PCALL_RES(lua_pcall(L, 6, 1, error_handler)); | |||
bool retval = lua_toboolean(L, -1); | |||
bool retval = readParam<bool>(L, -1); | |||
lua_pop(L, 2); // Pop object and error handler | |||
return retval; | |||
} | |||
@@ -285,7 +285,7 @@ bool ScriptApiEntity::luaentity_on_death(u16 id, ServerActiveObject *killer) | |||
setOriginFromTable(object); | |||
PCALL_RES(lua_pcall(L, 2, 1, error_handler)); | |||
bool retval = lua_toboolean(L, -1); | |||
bool retval = readParam<bool>(L, -1); | |||
lua_pop(L, 2); // Pop object and error handler | |||
return retval; | |||
} | |||
@@ -116,12 +116,12 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env) | |||
while (lua_next(L, table)) { | |||
// key at index -2 and value at index -1 | |||
luaL_checktype(L, -1, LUA_TSTRING); | |||
trigger_contents.insert(lua_tostring(L, -1)); | |||
trigger_contents.insert(readParam<std::string>(L, -1)); | |||
// removes value, keeps key for next iteration | |||
lua_pop(L, 1); | |||
} | |||
} else if (lua_isstring(L, -1)) { | |||
trigger_contents.insert(lua_tostring(L, -1)); | |||
trigger_contents.insert(readParam<std::string>(L, -1)); | |||
} | |||
lua_pop(L, 1); | |||
@@ -133,12 +133,12 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env) | |||
while (lua_next(L, table)) { | |||
// key at index -2 and value at index -1 | |||
luaL_checktype(L, -1, LUA_TSTRING); | |||
required_neighbors.insert(lua_tostring(L, -1)); | |||
required_neighbors.insert(readParam<std::string>(L, -1)); | |||
// removes value, keeps key for next iteration | |||
lua_pop(L, 1); | |||
} | |||
} else if (lua_isstring(L, -1)) { | |||
required_neighbors.insert(lua_tostring(L, -1)); | |||
required_neighbors.insert(readParam<std::string>(L, -1)); | |||
} | |||
lua_pop(L, 1); | |||
@@ -185,12 +185,12 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env) | |||
while (lua_next(L, table)) { | |||
// key at index -2 and value at index -1 | |||
luaL_checktype(L, -1, LUA_TSTRING); | |||
trigger_contents.insert(lua_tostring(L, -1)); | |||
trigger_contents.insert(readParam<std::string>(L, -1)); | |||
// removes value, keeps key for next iteration | |||
lua_pop(L, 1); | |||
} | |||
} else if (lua_isstring(L, -1)) { | |||
trigger_contents.insert(lua_tostring(L, -1)); | |||
trigger_contents.insert(readParam<std::string>(L, -1)); | |||
} | |||
lua_pop(L, 1); | |||
@@ -56,8 +56,5 @@ protected: | |||
bool getItemCallback(const char *name, const char *callbackname, const v3s16 *p = nullptr); | |||
void pushPointedThing(const PointedThing& pointed); | |||
}; | |||
#endif /* S_ITEM_H_ */ |
@@ -198,7 +198,7 @@ bool ScriptApiNode::node_on_flood(v3s16 p, MapNode node, MapNode newnode) | |||
pushnode(L, newnode, ndef); | |||
PCALL_RES(lua_pcall(L, 3, 1, error_handler)); | |||
lua_remove(L, error_handler); | |||
return (bool) lua_isboolean(L, -1) && (bool) lua_toboolean(L, -1) == true; | |||
return readParam<bool>(L, -1, false); | |||
} | |||
void ScriptApiNode::node_after_destruct(v3s16 p, MapNode node) | |||
@@ -237,7 +237,7 @@ bool ScriptApiNode::node_on_timer(v3s16 p, MapNode node, f32 dtime) | |||
lua_pushnumber(L,dtime); | |||
PCALL_RES(lua_pcall(L, 2, 1, error_handler)); | |||
lua_remove(L, error_handler); | |||
return (bool) lua_isboolean(L, -1) && (bool) lua_toboolean(L, -1) == true; | |||
return readParam<bool>(L, -1, false); | |||
} | |||
void ScriptApiNode::node_on_receive_fields(v3s16 p, | |||
@@ -74,7 +74,7 @@ bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player, | |||
push_v3f(L, dir); | |||
lua_pushnumber(L, damage); | |||
runCallbacks(6, RUN_CALLBACKS_MODE_OR); | |||
return lua_toboolean(L, -1); | |||
return readParam<bool>(L, -1); | |||
} | |||
s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player, | |||
@@ -111,8 +111,7 @@ bool ScriptApiPlayer::on_respawnplayer(ServerActiveObject *player) | |||
// Call callbacks | |||
objectrefGetOrCreate(L, player); | |||
runCallbacks(1, RUN_CALLBACKS_MODE_OR); | |||
bool positioning_handled_by_some = lua_toboolean(L, -1); | |||
return positioning_handled_by_some; | |||
return readParam<bool>(L, -1); | |||
} | |||
bool ScriptApiPlayer::on_prejoinplayer( | |||
@@ -129,7 +128,7 @@ bool ScriptApiPlayer::on_prejoinplayer( | |||
lua_pushstring(L, ip.c_str()); | |||
runCallbacks(2, RUN_CALLBACKS_MODE_OR); | |||
if (lua_isstring(L, -1)) { | |||
reason->assign(lua_tostring(L, -1)); | |||
reason->assign(readParam<std::string>(L, -1)); | |||
return true; | |||
} | |||
return false; | |||
@@ -261,7 +261,7 @@ void ScriptApiSecurity::initializeSecurityClient() | |||
static const char *os_whitelist[] = { | |||
"clock", | |||
"date", | |||
"difftime", | |||
"difftime", | |||
"time", | |||
"setlocale", | |||
}; | |||
@@ -526,7 +526,7 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path, | |||
// Get mod name | |||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME); | |||
if (lua_isstring(L, -1)) { | |||
std::string mod_name = lua_tostring(L, -1); | |||
std::string mod_name = readParam<std::string>(L, -1); | |||
// Builtin can access anything | |||
if (mod_name == BUILTIN_MOD_NAME) { | |||
@@ -649,7 +649,7 @@ int ScriptApiSecurity::sl_g_loadfile(lua_State *L) | |||
lua_pop(L, 1); | |||
if (script->getType() == ScriptingType::Client) { | |||
std:: string display_path = lua_tostring(L, 1); | |||
std::string display_path = readParam<std::string>(L, 1); | |||
const std::string *path = script->getClient()->getModFile(display_path); | |||
if (!path) { | |||
std::string error_msg = "Coudln't find script called:" + display_path; | |||
@@ -88,7 +88,7 @@ void ScriptApiServer::readPrivileges(int index, std::set<std::string> &result) | |||
while (lua_next(L, index) != 0) { | |||
// key at index -2 and value at index -1 | |||
std::string key = luaL_checkstring(L, -2); | |||
bool value = lua_toboolean(L, -1); | |||
bool value = readParam<bool>(L, -1); | |||
if (value) | |||
result.insert(key); | |||
// removes value, keeps key for next iteration | |||
@@ -143,8 +143,7 @@ bool ScriptApiServer::on_chat_message(const std::string &name, | |||
lua_pushstring(L, name.c_str()); | |||
lua_pushstring(L, message.c_str()); | |||
runCallbacks(2, RUN_CALLBACKS_MODE_OR_SC); | |||
bool ate = lua_toboolean(L, -1); | |||
return ate; | |||
return readParam<bool>(L, -1); | |||
} | |||
void ScriptApiServer::on_mods_loaded() | |||
@@ -156,7 +156,7 @@ int LuaAreaStore::l_get_areas_in_area(lua_State *L) | |||
bool include_data = false; | |||
bool accept_overlap = false; | |||
if (lua_isboolean(L, 4)) { | |||
accept_overlap = lua_toboolean(L, 4); | |||
accept_overlap = readParam<bool>(L, 4); | |||
get_data_and_border_flags(L, 5, &include_borders, &include_data); | |||
} | |||
std::vector<Area *> res; | |||
@@ -329,7 +329,7 @@ int LuaAreaStore::create_object(lua_State *L) | |||
NO_MAP_LOCK_REQUIRED; | |||
LuaAreaStore *o = (lua_isstring(L, 1)) ? | |||
new LuaAreaStore(lua_tostring(L, 1)) : | |||
new LuaAreaStore(readParam<std::string>(L, 1)) : | |||
new LuaAreaStore(); | |||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o; | |||
@@ -63,8 +63,8 @@ GUIEngine *ModApiBase::getGuiEngine(lua_State *L) | |||
std::string ModApiBase::getCurrentModPath(lua_State *L) | |||
{ | |||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME); | |||
const char *current_mod_name = lua_tostring(L, -1); | |||
if (!current_mod_name) | |||
std::string current_mod_name = readParam<std::string>(L, -1, ""); | |||
if (current_mod_name.empty()) | |||
return "."; | |||
const ModSpec *mod = getServer(L)->getModSpec(current_mod_name); | |||
@@ -85,8 +85,3 @@ bool ModApiBase::registerFunction(lua_State *L, const char *name, | |||
return true; | |||
} | |||
bool ModApiBase::isNaN(lua_State *L, int idx) | |||
{ | |||
return lua_type(L, idx) == LUA_TNUMBER && std::isnan(lua_tonumber(L, idx)); | |||
} |
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., | |||
#include "common/c_types.h" | |||
#include "common/c_internal.h" | |||
#include "common/helper.h" | |||
#include "gamedef.h" | |||
extern "C" { | |||
@@ -38,7 +39,7 @@ class Server; | |||
class Environment; | |||
class GUIEngine; | |||
class ModApiBase { | |||
class ModApiBase : protected LuaHelper { | |||
public: | |||
static ScriptApiBase* getScriptApiBase(lua_State *L); | |||
@@ -70,8 +71,6 @@ public: | |||
const char* name, | |||
lua_CFunction func, | |||
int top); | |||
static bool isNaN(lua_State *L, int idx); | |||
}; | |||
#endif /* L_BASE_H_ */ |
@@ -36,18 +36,29 @@ with this program; if not, write to the Free Software Foundation, Inc., | |||
extern MainGameCallback *g_gamecallback; | |||
// get_current_modname() | |||
int ModApiClient::l_get_current_modname(lua_State *L) | |||
{ | |||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME); | |||
return 1; | |||
} | |||
// get_modpath(modname) | |||
int ModApiClient::l_get_modpath(lua_State *L) | |||
{ | |||
std::string modname = readParam<std::string>(L, 1); | |||
// Client mods use a virtual filesystem, see Client::scanModSubfolder() | |||
std::string path = modname + ":"; | |||
lua_pushstring(L, path.c_str()); | |||
return 1; | |||
} | |||
// get_last_run_mod() | |||
int ModApiClient::l_get_last_run_mod(lua_State *L) | |||
{ | |||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME); | |||
const char *current_mod = lua_tostring(L, -1); | |||
if (current_mod == NULL || current_mod[0] == '\0') { | |||
std::string current_mod = readParam<std::string>(L, -1, ""); | |||
if (current_mod.empty()) { | |||
lua_pop(L, 1); | |||
lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str()); | |||
} | |||
@@ -90,15 +101,9 @@ int ModApiClient::l_display_chat_message(lua_State *L) | |||
// send_chat_message(message) | |||
int ModApiClient::l_send_chat_message(lua_State *L) | |||
{ | |||
if (!lua_isstring(L, 1)) | |||
return 0; | |||
// If server disabled this API, discard | |||
if (getClient(L)->checkCSMFlavourLimit(CSMFlavourLimit::CSM_FL_CHAT_MESSAGES)) | |||
return 0; | |||
std::string message = luaL_checkstring(L, 1); | |||
getClient(L)->sendChatMessage(utf8_to_wide(message)); | |||
if (!lua_isstring (L, 1)) return 0; | |||
std::string message = luaL_checkstring (L, 1); | |||
getClient (L)->sendChatMessage (utf8_to_wide (message)); | |||
return 0; | |||
} | |||
@@ -191,9 +196,14 @@ int ModApiClient::l_get_node_or_nil(lua_State *L) | |||
int ModApiClient::l_get_language(lua_State *L) | |||
{ | |||
char *locale = setlocale(LC_ALL, ""); | |||
char *locale = setlocale(LC_MESSAGES, NULL); | |||
std::string lang = gettext("LANG_CODE"); | |||
if (lang == "LANG_CODE") | |||
lang = ""; | |||
lua_pushstring(L, locale); | |||
return 1; | |||
lua_pushstring(L, lang.c_str()); | |||
return 2; | |||
} | |||
int ModApiClient::l_get_wielded_item(lua_State *L) | |||
@@ -296,7 +306,7 @@ int ModApiClient::l_get_item_def(lua_State *L) | |||
if (!lua_isstring(L, 1)) | |||
return 0; | |||
const std::string &name(lua_tostring(L, 1)); | |||
std::string name = readParam<std::string>(L, 1); | |||
if (!idef->isKnown(name)) | |||
return 0; | |||
const ItemDefinition &def = idef->get(name); | |||
@@ -321,7 +331,7 @@ int ModApiClient::l_get_node_def(lua_State *L) | |||
if (getClient(L)->checkCSMFlavourLimit(CSMFlavourLimit::CSM_FL_READ_NODEDEFS)) | |||
return 0; | |||
const std::string &name = lua_tostring(L, 1); | |||
std::string name = readParam<std::string>(L, 1); | |||
const ContentFeatures &cf = ndef->get(ndef->getId(name)); | |||
if (cf.name != name) // Unknown node. | name = <whatever>, cf.name = ignore | |||
return 0; | |||
@@ -352,6 +362,7 @@ int ModApiClient::l_get_builtin_path(lua_State *L) | |||
void ModApiClient::Initialize(lua_State *L, int top) | |||
{ | |||
API_FCT(get_current_modname); | |||
API_FCT(get_modpath); | |||
API_FCT(print); | |||
API_FCT(display_chat_message); | |||
API_FCT(send_chat_message); | |||
@@ -31,6 +31,9 @@ private: | |||
// get_current_modname() | |||
static int l_get_current_modname(lua_State *L); | |||
// get_modpath(modname) | |||
static int l_get_modpath(lua_State *L); | |||
// print(text) | |||
static int l_print(lua_State *L); | |||
@@ -57,7 +57,7 @@ bool ModApiCraft::readCraftRecipeShaped(lua_State *L, int index, | |||
// key at index -2 and value at index -1 | |||
if(!lua_isstring(L, -1)) | |||
return false; | |||
recipe.push_back(lua_tostring(L, -1)); | |||
recipe.push_back(readParam<std::string>(L, -1)); | |||
// removes value, keeps key for next iteration | |||
lua_pop(L, 1); | |||
colcount++; | |||
@@ -90,7 +90,7 @@ bool ModApiCraft::readCraftRecipeShapeless(lua_State *L, int index, | |||
// key at index -2 and value at index -1 | |||
if(!lua_isstring(L, -1)) | |||
return false; | |||
recipe.push_back(lua_tostring(L, -1)); | |||
recipe.push_back(readParam<std::string>(L, -1)); | |||
// removes value, keeps key for next iteration | |||
lua_pop(L, 1); | |||
} | |||
@@ -115,12 +115,12 @@ bool ModApiCraft::readCraftReplacements(lua_State *L, int index, | |||
lua_rawgeti(L, -1, 1); | |||
if(!lua_isstring(L, -1)) | |||
return false; | |||
std::string replace_from = lua_tostring(L, -1); | |||
std::string replace_from = readParam<std::string>(L, -1); | |||
lua_pop(L, 1); | |||
lua_rawgeti(L, -1, 2); | |||
if(!lua_isstring(L, -1)) | |||
return false; | |||
std::string replace_to = lua_tostring(L, -1); | |||
std::string replace_to = readParam<std::string>(L, -1); | |||
lua_pop(L, 1); | |||
replacements.pairs.push_back( | |||
std::make_pair(replace_from, replace_to)); | |||
@@ -165,10 +165,10 @@ int LuaRaycast::create_object(lua_State *L) | |||
v3f pos1 = checkFloatPos(L, 1); | |||
v3f pos2 = checkFloatPos(L, 2); | |||
if (lua_isboolean(L, 3)) { | |||
objects = lua_toboolean(L, 3); | |||
objects = readParam<bool>(L, 3); | |||
} | |||
if (lua_isboolean(L, 4)) { | |||
liquids = lua_toboolean(L, 4); | |||
liquids = readParam<bool>(L, 4); | |||
} | |||
LuaRaycast *o = new LuaRaycast(core::line3d<f32>(pos1, pos2), | |||
@@ -599,9 +599,13 @@ int ModApiEnvMod::l_add_entity(lua_State *L) | |||
// Do it | |||
ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, staticdata); | |||
int objectid = env->addActiveObject(obj); | |||
// If failed to add, return nothing (reads as nil) | |||
if(objectid == 0) | |||
return 0; | |||
if(objectid == 0) return 0; | |||
// If already deleted (can happen in on_activate), return nil | |||
if (obj->isGone()) return 0; | |||
// Return ObjectRef | |||
getScriptApiBase(L)->objectrefGetOrCreate(L, obj); | |||
return 1; | |||
@@ -687,7 +691,7 @@ int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L) | |||
// Do it | |||
v3f pos = checkFloatPos(L, 1); | |||
float radius = luaL_checknumber(L, 2) * BS; | |||
float radius = readParam<float>(L, 2) * BS; | |||
std::vector<u16> ids; | |||
env->getObjectsInsideRadius(ids, pos, radius); | |||
ScriptApiBase *script = getScriptApiBase(L); | |||
@@ -711,7 +715,7 @@ int ModApiEnvMod::l_set_timeofday(lua_State *L) | |||
GET_ENV_PTR; | |||
// Do it | |||
float timeofday_f = luaL_checknumber(L, 1); | |||
float timeofday_f = readParam<float>(L, 1); | |||
sanity_check(timeofday_f >= 0.0 && timeofday_f <= 1.0); | |||
int timeofday_mh = (int)(timeofday_f * 24000.0); | |||
// This should be set directly in the environment but currently | |||
@@ -778,15 +782,15 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) | |||
while (lua_next(L, 3) != 0) { | |||
// key at index -2 and value at index -1 | |||
luaL_checktype(L, -1, LUA_TSTRING); | |||
ndef->getIds(lua_tostring(L, -1), filter); | |||
ndef->getIds(readParam<std::string>(L, -1), filter); | |||
// removes value, keeps key for next iteration | |||
lua_pop(L, 1); | |||
} | |||
} else if (lua_isstring(L, 3)) { | |||
ndef->getIds(lua_tostring(L, 3), filter); | |||
ndef->getIds(readParam<std::string>(L, 3), filter); | |||
} | |||
int start_radius = (lua_toboolean(L, 4)) ? 0 : 1; | |||
int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1; | |||
#ifndef SERVER | |||
// Client API limitations | |||
@@ -836,12 +840,12 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) | |||
while (lua_next(L, 3) != 0) { | |||
// key at index -2 and value at index -1 | |||
luaL_checktype(L, -1, LUA_TSTRING); | |||
ndef->getIds(lua_tostring(L, -1), filter); | |||
ndef->getIds(readParam<std::string>(L, -1), filter); | |||
// removes value, keeps key for next iteration | |||
lua_pop(L, 1); | |||
} | |||
} else if (lua_isstring(L, 3)) { | |||
ndef->getIds(lua_tostring(L, 3), filter); | |||
ndef->getIds(readParam<std::string>(L, 3), filter); | |||
} | |||
std::unordered_map<content_t, u32> individual_count; | |||
@@ -901,12 +905,12 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L) | |||
while (lua_next(L, 3) != 0) { | |||
// key at index -2 and value at index -1 | |||
luaL_checktype(L, -1, LUA_TSTRING); | |||
ndef->getIds(lua_tostring(L, -1), filter); | |||
ndef->getIds(readParam<std::string>(L, -1), filter); | |||
// removes value, keeps key for next iteration | |||
lua_pop(L, 1); | |||
} | |||
} else if (lua_isstring(L, 3)) { | |||
ndef->getIds(lua_tostring(L, 3), filter); | |||
ndef->getIds(readParam<std::string>(L, 3), filter); | |||
} | |||
lua_newtable(L); | |||
@@ -943,8 +947,8 @@ int ModApiEnvMod::l_get_perlin(lua_State *L) | |||
} else { | |||
params.seed = luaL_checkint(L, 1); | |||
params.octaves = luaL_checkint(L, 2); | |||
params.persist = luaL_checknumber(L, 3); | |||
params.spread = v3f(1, 1, 1) * luaL_checknumber(L, 4); | |||
params.persist = readParam<float>(L, 3); | |||
params.spread = v3f(1, 1, 1) * readParam<float>(L, 4); | |||
} | |||
params.seed += (int)env->getServerMap().getSeed(); | |||
@@ -59,7 +59,7 @@ void ModApiHttp::read_http_fetch_request(lua_State *L, HTTPFetchRequest &req) | |||
lua_pop(L, 1); | |||
} | |||
} else if (lua_isstring(L, 2)) { | |||
req.post_data = lua_tostring(L, 2); | |||
req.post_data = readParam<std::string>(L, 2); | |||
} | |||
lua_pop(L, 1); | |||
@@ -154,7 +154,7 @@ int ModApiHttp::l_request_http_api(lua_State *L) | |||
return 0; | |||
} | |||
const char *mod_name = lua_tostring(L, -1); | |||
std::string mod_name = readParam<std::string>(L, -1); | |||
std::string http_mods = g_settings->get("secure.http_mods"); | |||
http_mods.erase(std::remove(http_mods.begin(), http_mods.end(), ' '), http_mods.end()); | |||
std::vector<std::string> mod_list_http = str_split(http_mods, ','); | |||
@@ -336,7 +336,7 @@ int InvRef::l_contains_item(lua_State *L) | |||
InventoryList *list = getlist(L, ref, listname); | |||
bool match_meta = false; | |||
if (lua_isboolean(L, 4)) | |||
match_meta = lua_toboolean(L, 4); | |||
match_meta = readParam<bool>(L, 4); | |||
if (list) { | |||
lua_pushboolean(L, list->containsItem(item, match_meta)); | |||
} else { | |||
@@ -528,7 +528,7 @@ int ModApiInventory::l_create_detached_inventory_raw(lua_State *L) | |||
{ | |||
NO_MAP_LOCK_REQUIRED; | |||
const char *name = luaL_checkstring(L, 1); | |||
const char *player = lua_isstring(L, 2) ? lua_tostring(L, 2) : ""; | |||
std::string player = readParam<std::string>(L, 2, ""); | |||
if (getServer(L)->createDetachedInventory(name, player) != NULL) { | |||
InventoryLocation loc; | |||
loc.setDetached(name); | |||
@@ -515,7 +515,7 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) | |||
std::string name; | |||
lua_getfield(L, table, "name"); | |||
if(lua_isstring(L, -1)){ | |||
name = lua_tostring(L, -1); | |||
name = readParam<std::string>(L, -1); | |||
verbosestream<<"register_item_raw: "<<name<<std::endl; | |||
} else { | |||
throw LuaError("register_item_raw: name is not defined or not a string"); | |||
@@ -81,7 +81,7 @@ int ModApiMainMenu::getBoolData(lua_State *L, std::string name,bool& valid) | |||
} | |||
valid = true; | |||
return lua_toboolean(L, -1); | |||
return readParam<bool>(L, -1); | |||
} | |||
/******************************************************************************/ | |||
@@ -156,7 +156,7 @@ int ModApiMainMenu::l_set_background(lua_State *L) | |||
unsigned int minsize = 16; | |||
if (!lua_isnone(L, 3)) { | |||
tile_image = lua_toboolean(L, 3); | |||
tile_image = readParam<bool>(L, 3); | |||
} | |||
if (!lua_isnone(L, 4)) { | |||
@@ -193,7 +193,7 @@ int ModApiMainMenu::l_set_clouds(lua_State *L) | |||
GUIEngine* engine = getGuiEngine(L); | |||
sanity_check(engine != NULL); | |||
bool value = lua_toboolean(L,1); | |||
bool value = readParam<bool>(L,1); | |||
engine->m_clouds_enabled = value; | |||
@@ -619,7 +619,8 @@ int ModApiMainMenu::l_set_topleft_text(lua_State *L) | |||
int ModApiMainMenu::l_get_mapgen_names(lua_State *L) | |||
{ | |||
std::vector<const char *> names; | |||
Mapgen::getMapgenNames(&names, lua_toboolean(L, 1)); | |||
bool include_hidden = lua_isboolean(L, 1) && readParam<bool>(L, 1); | |||
Mapgen::getMapgenNames(&names, include_hidden); | |||
lua_newtable(L); | |||
for (size_t i = 0; i != names.size(); i++) { | |||
@@ -714,7 +715,7 @@ int ModApiMainMenu::l_copy_dir(lua_State *L) | |||
if ((!lua_isnone(L,3)) && | |||
(!lua_isnil(L,3))) { | |||
keep_source = lua_toboolean(L,3); | |||
keep_source = readParam<bool>(L,3); | |||
} | |||
std::string absolute_destination = fs::RemoveRelativePathComponents(destination); | |||
@@ -859,7 +860,7 @@ int ModApiMainMenu::l_show_path_select_dialog(lua_State *L) | |||
const char *formname= luaL_checkstring(L, 1); | |||
const char *title = luaL_checkstring(L, 2); | |||
bool is_file_select = lua_toboolean(L, 3); | |||
bool is_file_select = readParam<bool>(L, 3); | |||
GUIFileSelectMenu* fileOpenMenu = | |||
new GUIFileSelectMenu(RenderingEngine::get_gui_env(), | |||
@@ -845,26 +845,26 @@ int ModApiMapgen::l_set_mapgen_params(lua_State *L) | |||
lua_getfield(L, 1, "mgname"); | |||
if (lua_isstring(L, -1)) | |||
settingsmgr->setMapSetting("mg_name", lua_tostring(L, -1), true); | |||
settingsmgr->setMapSetting("mg_name", readParam<std::string>(L, -1), true); | |||
lua_getfield(L, 1, "seed"); | |||
if (lua_isnumber(L, -1)) | |||
settingsmgr->setMapSetting("seed", lua_tostring(L, -1), true); | |||
settingsmgr->setMapSetting("seed", readParam<std::string>(L, -1), true); | |||
lua_getfield(L, 1, "water_level"); | |||
if (lua_isnumber(L, -1)) | |||
settingsmgr->setMapSetting("water_level", lua_tostring(L, -1), true); | |||
settingsmgr->setMapSetting("water_level", readParam<std::string>(L, -1), true); | |||
lua_getfield(L, 1, "chunksize"); | |||
if (lua_isnumber(L, -1)) | |||
settingsmgr->setMapSetting("chunksize", lua_tostring(L, -1), true); | |||
settingsmgr->setMapSetting("chunksize", readParam<std::string>(L, -1), true); | |||
warn_if_field_exists(L, 1, "flagmask", | |||
"Deprecated: flags field now includes unset flags."); | |||
lua_getfield(L, 1, "flags"); | |||
if (lua_isstring(L, -1)) | |||
settingsmgr->setMapSetting("mg_flags", lua_tostring(L, -1), true); | |||
settingsmgr->setMapSetting("mg_flags", readParam<std::string>(L, -1), true); | |||
return 0; | |||
} | |||
@@ -914,7 +914,7 @@ int ModApiMapgen::l_set_mapgen_setting(lua_State *L) | |||
const char *name = luaL_checkstring(L, 1); | |||
const char *value = luaL_checkstring(L, 2); | |||
bool override_meta = lua_isboolean(L, 3) ? lua_toboolean(L, 3) : false; | |||
bool override_meta = readParam<bool>(L, 3, false); | |||
if (!settingsmgr->setMapSetting(name, value, override_meta)) { | |||
errorstream << "set_mapgen_setting: cannot set '" | |||
@@ -943,7 +943,7 @@ int ModApiMapgen::l_set_mapgen_setting_noiseparams(lua_State *L) | |||
return 0; | |||
} | |||
bool override_meta = lua_isboolean(L, 3) ? lua_toboolean(L, 3) : false; | |||
bool override_meta = readParam<bool>(L, 3, false); | |||
if (!settingsmgr->setMapSettingNoiseParams(name, &np, override_meta)) { | |||
errorstream << "set_mapgen_setting_noiseparams: cannot set '" | |||
@@ -953,13 +953,11 @@ int ModApiMapgen::l_set_mapgen_setting_noiseparams(lua_State *L) | |||
return 0; | |||
} | |||
// set_noiseparams(name, noiseparams, set_default) | |||
// set global config values for noise parameters | |||
int ModApiMapgen::l_set_noiseparams(lua_State *L) | |||
{ | |||
NO_MAP_LOCK_REQUIRED; | |||
const char *name = luaL_checkstring(L, 1); | |||
NoiseParams np; | |||
@@ -970,13 +968,10 @@ int ModApiMapgen::l_set_noiseparams(lua_State *L) | |||
} | |||
bool set_default = lua_isboolean(L, 3) ? lua_toboolean(L, 3) : true; | |||
g_settings->setNoiseParams(name, np, set_default); | |||
return 0; | |||
} | |||
// get_noiseparams(name) | |||
int ModApiMapgen::l_get_noiseparams(lua_State *L) | |||
{ | |||
@@ -1589,14 +1584,14 @@ int ModApiMapgen::l_place_schematic(lua_State *L) | |||
//// Read rotation | |||
int rot = ROTATE_0; | |||
const char *enumstr = lua_tostring(L, 3); | |||
if (enumstr) | |||
string_to_enum(es_Rotation, rot, std::string(enumstr)); | |||
std::string enumstr = readParam<std::string>(L, 3, ""); | |||
if (!enumstr.empty()) | |||
string_to_enum(es_Rotation, rot, enumstr); | |||
//// Read force placement | |||
bool force_placement = true; | |||
if (lua_isboolean(L, 5)) | |||
force_placement = lua_toboolean(L, 5); | |||
force_placement = readParam<bool>(L, 5); | |||
//// Read node replacements | |||
StringMap replace_names; | |||
@@ -1637,14 +1632,14 @@ int ModApiMapgen::l_place_schematic_on_vmanip(lua_State *L) | |||
//// Read rotation | |||
int rot = ROTATE_0; | |||
const char *enumstr = lua_tostring(L, 4); | |||
if (enumstr) | |||
std::string enumstr = readParam<std::string>(L, 4, ""); | |||
if (!enumstr.empty()) | |||
string_to_enum(es_Rotation, rot, std::string(enumstr)); | |||
//// Read force placement | |||
bool force_placement = true; | |||
if (lua_isboolean(L, 6)) | |||
force_placement = lua_toboolean(L, 6); | |||
force_placement = readParam<bool>(L, 6); | |||
//// Read node replacements | |||
StringMap replace_names; | |||
@@ -1695,9 +1690,9 @@ int ModApiMapgen::l_serialize_schematic(lua_State *L) | |||
//// Read format of definition to save as | |||
int schem_format = SCHEM_FMT_MTS; | |||
const char *enumstr = lua_tostring(L, 2); | |||
if (enumstr) | |||
string_to_enum(es_SchematicFormatType, schem_format, std::string(enumstr)); | |||
std::string enumstr = readParam<std::string>(L, 2, ""); | |||
if (!enumstr.empty()) | |||
string_to_enum(es_SchematicFormatType, schem_format, enumstr); | |||
//// Serialize to binary string | |||
std::ostringstream os(std::ios_base::binary); | |||
@@ -190,7 +190,7 @@ int MetaDataRef::l_set_float(lua_State *L) | |||
MetaDataRef *ref = checkobject(L, 1); | |||
std::string name = luaL_checkstring(L, 2); | |||
float a = luaL_checknumber(L, 3); | |||
float a = readParam<float>(L, 3); | |||
std::string str = ftos(a); | |||
Metadata *meta = ref->getmeta(true); | |||
@@ -276,7 +276,7 @@ bool MetaDataRef::handleFromTable(lua_State *L, int table, Metadata *meta) | |||
lua_pushnil(L); | |||
while (lua_next(L, fieldstable) != 0) { | |||
// key at index -2 and value at index -1 | |||
std::string name = lua_tostring(L, -2); | |||
std::string name = readParam<std::string>(L, -2); | |||
size_t cl; | |||
const char *cs = lua_tolstring(L, -1, &cl); | |||
meta->setString(name, std::string(cs, cl)); | |||
@@ -109,12 +109,12 @@ int NodeMetaRef::l_mark_as_private(lua_State *L) | |||
while (lua_next(L, 2) != 0) { | |||
// key at index -2 and value at index -1 | |||
luaL_checktype(L, -1, LUA_TSTRING); | |||
meta->markPrivate(lua_tostring(L, -1), true); | |||
meta->markPrivate(readParam<std::string>(L, -1), true); | |||
// removes value, keeps key for next iteration | |||
lua_pop(L, 1); | |||
} | |||
} else if (lua_isstring(L, 2)) { | |||
meta->markPrivate(lua_tostring(L, 2), true); | |||
meta->markPrivate(readParam<std::string>(L, 2), true); | |||
} | |||
ref->reportMetadataChange(); | |||
@@ -43,8 +43,8 @@ int NodeTimerRef::l_set(lua_State *L) | |||
NodeTimerRef *o = checkobject(L, 1); | |||
ServerEnvironment *env = o->m_env; | |||
if(env == NULL) return 0; | |||
f32 t = luaL_checknumber(L,2); | |||
f32 e = luaL_checknumber(L,3); | |||
f32 t = readParam<float>(L,2); | |||
f32 e = readParam<float>(L,3); | |||
env->getMap().setNodeTimer(NodeTimer(t, e, o->m_p)); | |||
return 0; | |||
} | |||
@@ -55,7 +55,7 @@ int NodeTimerRef::l_start(lua_State *L) | |||
NodeTimerRef *o = checkobject(L, 1); | |||
ServerEnvironment *env = o->m_env; | |||
if(env == NULL) return 0; | |||
f32 t = luaL_checknumber(L,2); | |||
f32 t = readParam<float>(L,2); | |||
env->getMap().setNodeTimer(NodeTimer(t, 0, o->m_p)); | |||
return 0; | |||
} | |||
@@ -75,8 +75,8 @@ int LuaPerlinNoise::create_object(lua_State *L) | |||
} else { | |||
params.seed = luaL_checkint(L, 1); | |||
params.octaves = luaL_checkint(L, 2); | |||
params.persist = luaL_checknumber(L, 3); | |||
params.spread = v3f(1, 1, 1) * luaL_checknumber(L, 4); | |||
params.persist = readParam<float>(L, 3); | |||
params.spread = v3f(1, 1, 1) * readParam<float>(L, 4); | |||
} | |||
LuaPerlinNoise *o = new LuaPerlinNoise(¶ms); | |||
@@ -197,7 +197,7 @@ int ObjectRef::l_move_to(lua_State *L) | |||
// pos | |||
v3f pos = checkFloatPos(L, 2); | |||
// continuous | |||
bool continuous = lua_toboolean(L, 3); | |||
bool continuous = readParam<bool>(L, 3); | |||
// Do it | |||
co->moveTo(pos, continuous); | |||
return 0; | |||
@@ -284,7 +284,8 @@ int ObjectRef::l_set_hp(lua_State *L) | |||
lua_pushvalue(L, 3); | |||
lua_getfield(L, -1, "type"); | |||
if (lua_isstring(L, -1) && !reason.setTypeFromString(lua_tostring(L, -1))) { | |||
if (lua_isstring(L, -1) && | |||
!reason.setTypeFromString(readParam<std::string>(L, -1))) { | |||
errorstream << "Bad type given!" << std::endl; | |||
} | |||
lua_pop(L, 1); | |||
@@ -514,7 +515,7 @@ int ObjectRef::l_set_animation(lua_State *L) | |||
frame_blend = lua_tonumber(L, 4); | |||
bool frame_loop = true; | |||
if (lua_isboolean(L, 5)) | |||
frame_loop = lua_toboolean(L, 5); | |||
frame_loop = readParam<bool>(L, 5); | |||
co->setAnimation(frames, frame_speed, frame_blend, frame_loop); | |||
return 0; | |||
} | |||
@@ -679,7 +680,7 @@ int ObjectRef::l_set_bone_position(lua_State *L) | |||
// Do it | |||
std::string bone = ""; | |||
if (!lua_isnil(L, 2)) | |||
bone = lua_tostring(L, 2); | |||
bone = readParam<std::string>(L, 2); | |||
v3f position = v3f(0, 0, 0); | |||
if (!lua_isnil(L, 3)) | |||
position = check_v3f(L, 3); | |||
@@ -701,7 +702,7 @@ int ObjectRef::l_get_bone_position(lua_State *L) | |||
// Do it | |||
std::string bone = ""; | |||
if (!lua_isnil(L, 2)) | |||
bone = lua_tostring(L, 2); | |||
bone = readParam<std::string>(L, 2); | |||
v3f position = v3f(0, 0, 0); | |||
v3f rotation = v3f(0, 0, 0); | |||
@@ -738,7 +739,7 @@ int ObjectRef::l_set_attach(lua_State *L) | |||
bone = ""; | |||
if (!lua_isnil(L, 3)) | |||
bone = lua_tostring(L, 3); | |||
bone = readParam<std::string>(L, 3); | |||
position = v3f(0, 0, 0); | |||
if (!lua_isnil(L, 4)) | |||
position = read_v3f(L, 4); | |||
@@ -976,7 +977,7 @@ int ObjectRef::l_set_yaw(lua_State *L) | |||
if (isNaN(L, 2)) | |||
throw LuaError("ObjectRef::set_yaw: NaN value is not allowed."); | |||
float yaw = luaL_checknumber(L, 2) * core::RADTODEG; | |||
float yaw = readParam<float>(L, 2) * core::RADTODEG; | |||
// Do it | |||
co->setYaw(yaw); | |||
return 0; | |||
@@ -1063,7 +1064,7 @@ int ObjectRef::l_set_sprite(lua_State *L) | |||
framelength = lua_tonumber(L, 4); | |||
bool select_horiz_by_yawpitch = false; | |||
if (!lua_isnil(L, 5)) | |||
select_horiz_by_yawpitch = lua_toboolean(L, 5); | |||
select_horiz_by_yawpitch = readParam<bool>(L, 5); | |||
co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch); | |||
return 0; | |||
} | |||
@@ -1220,7 +1221,7 @@ int ObjectRef::l_set_look_vertical(lua_State *L) | |||
ObjectRef *ref = checkobject(L, 1); | |||
PlayerSAO* co = getplayersao(ref); | |||
if (co == NULL) return 0; | |||
float pitch = luaL_checknumber(L, 2) * core::RADTODEG; | |||
float pitch = readParam<float>(L, 2) * core::RADTODEG; | |||
// Do it | |||
co->setPitchAndSend(pitch); | |||
return 1; | |||
@@ -1233,7 +1234,7 @@ int ObjectRef::l_set_look_horizontal(lua_State *L) | |||
ObjectRef *ref = checkobject(L, 1); | |||
PlayerSAO* co = getplayersao(ref); | |||
if (co == NULL) return 0; | |||
float yaw = luaL_checknumber(L, 2) * core::RADTODEG; | |||
float yaw = readParam<float>(L, 2) * core::RADTODEG; | |||
// Do it | |||
co->setYawAndSend(yaw); | |||
return 1; | |||
@@ -1251,7 +1252,7 @@ int ObjectRef::l_set_look_pitch(lua_State *L) | |||
ObjectRef *ref = checkobject(L, 1); | |||
PlayerSAO* co = getplayersao(ref); | |||
if (co == NULL) return 0; | |||
float pitch = luaL_checknumber(L, 2) * core::RADTODEG; | |||
float pitch = readParam<float>(L, 2) * core::RADTODEG; | |||
// Do it | |||
co->setPitchAndSend(pitch); | |||
return 1; | |||
@@ -1269,7 +1270,7 @@ int ObjectRef::l_set_look_yaw(lua_State *L) | |||
ObjectRef *ref = checkobject(L, 1); | |||
PlayerSAO* co = getplayersao(ref); | |||
if (co == NULL) return 0; | |||
float yaw = luaL_checknumber(L, 2) * core::RADTODEG; | |||
float yaw = readParam<float>(L, 2) * core::RADTODEG; | |||
// Do it | |||
co->setYawAndSend(yaw); | |||
return 1; | |||
@@ -1732,7 +1733,7 @@ int ObjectRef::l_hud_set_hotbar_image(lua_State *L) | |||
if (player == NULL) | |||
return 0; | |||
std::string name = lua_tostring(L, 2); | |||
std::string name = readParam<std::string>(L, 2); | |||
getServer(L)->hudSetHotbarImage(player, name); | |||
return 1; | |||
@@ -1761,7 +1762,7 @@ int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L) | |||
if (player == NULL) | |||
return 0; | |||
std::string name = lua_tostring(L, 2); | |||
std::string name = readParam<std::string>(L, 2); | |||
getServer(L)->hudSetHotbarSelectedImage(player, name); | |||
return 1; | |||
@@ -1801,7 +1802,7 @@ int ObjectRef::l_set_sky(lua_State *L) | |||
while (lua_next(L, 4) != 0) { | |||
// key at index -2 and value at index -1 | |||
if (lua_isstring(L, -1)) | |||
params.push_back(lua_tostring(L, -1)); | |||
params.push_back(readParam<std::string>(L, -1)); | |||
else | |||
params.push_back(""); | |||
// removes value, keeps key for next iteration | |||
@@ -1814,7 +1815,7 @@ int ObjectRef::l_set_sky(lua_State *L) | |||
bool clouds = true; | |||
if (lua_isboolean(L, 5)) | |||
clouds = lua_toboolean(L, 5); | |||
clouds = readParam<bool>(L, 5); | |||
if (!getServer(L)->setSky(player, bgcolor, type, params, clouds)) | |||
return 0; | |||
@@ -1890,7 +1891,7 @@ int ObjectRef::l_override_day_night_ratio(lua_State *L) | |||
float ratio = 0.0f; | |||
if (!lua_isnil(L, 2)) { | |||
do_override = true; | |||
ratio = luaL_checknumber(L, 2); | |||
ratio = readParam<float>(L, 2); | |||
} | |||
if (!getServer(L)->overrideDayNightRatio(player, do_override, ratio)) | |||
@@ -66,7 +66,7 @@ int ModApiParticles::l_add_particle(lua_State *L) | |||
acc = check_v3f(L, 3); | |||
expirationtime = luaL_checknumber(L, 4); | |||
size = luaL_checknumber(L, 5); | |||
collisiondetection = lua_toboolean(L, 6); | |||
collisiondetection = readParam<bool>(L, 6); | |||
texture = luaL_checkstring(L, 7); | |||
if (lua_gettop(L) == 8) // only spawn for a single player | |||
playername = luaL_checkstring(L, 8); | |||
@@ -177,7 +177,7 @@ int ModApiParticles::l_add_particlespawner(lua_State *L) | |||
maxexptime = luaL_checknumber(L, 10); | |||
minsize = luaL_checknumber(L, 11); | |||
maxsize = luaL_checknumber(L, 12); | |||
collisiondetection = lua_toboolean(L, 13); | |||
collisiondetection = readParam<bool>(L, 13); | |||
texture = luaL_checkstring(L, 14); | |||
if (lua_gettop(L) == 15) // only spawn for a single player | |||
playername = luaL_checkstring(L, 15); | |||
@@ -33,7 +33,7 @@ int ModApiServer::l_request_shutdown(lua_State *L) | |||
{ | |||
NO_MAP_LOCK_REQUIRED; | |||
const char *msg = lua_tolstring(L, 1, NULL); | |||
bool reconnect = lua_toboolean(L, 2); | |||
bool reconnect = readParam<bool>(L, 2); | |||
float seconds_before_shutdown = lua_tonumber(L, 3); | |||
getServer(L)->requestShutdown(msg ? msg : "", reconnect, seconds_before_shutdown); | |||
return 0; | |||
@@ -314,15 +314,11 @@ int ModApiServer::l_kick_player(lua_State *L) | |||
{ | |||
NO_MAP_LOCK_REQUIRED; | |||
const char *name = luaL_checkstring(L, 1); | |||
std::string message; | |||
std::string message("Kicked"); | |||