aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/script')
-rw-r--r--src/script/common/c_content.cpp44
-rw-r--r--src/script/common/c_content.h6
-rw-r--r--src/script/common/c_converter.cpp20
-rw-r--r--src/script/common/c_converter.h4
-rw-r--r--src/script/cpp_api/s_async.cpp3
-rw-r--r--src/script/cpp_api/s_async.h2
-rw-r--r--src/script/cpp_api/s_env.cpp4
-rw-r--r--src/script/cpp_api/s_node.cpp1
-rw-r--r--src/script/cpp_api/s_player.cpp6
-rw-r--r--src/script/cpp_api/s_player.h2
-rw-r--r--src/script/cpp_api/s_security.cpp148
-rw-r--r--src/script/cpp_api/s_security.h21
-rw-r--r--src/script/lua_api/l_areastore.cpp7
-rw-r--r--src/script/lua_api/l_craft.cpp92
-rw-r--r--src/script/lua_api/l_craft.h1
-rw-r--r--src/script/lua_api/l_env.cpp10
-rw-r--r--src/script/lua_api/l_inventory.cpp9
-rw-r--r--src/script/lua_api/l_inventory.h9
-rw-r--r--src/script/lua_api/l_item.cpp22
-rw-r--r--src/script/lua_api/l_item.h1
-rw-r--r--src/script/lua_api/l_mainmenu.cpp13
-rw-r--r--src/script/lua_api/l_mainmenu.h2
-rw-r--r--src/script/lua_api/l_mapgen.cpp218
-rw-r--r--src/script/lua_api/l_mapgen.h12
-rw-r--r--src/script/lua_api/l_nodetimer.cpp4
-rw-r--r--src/script/lua_api/l_noise.cpp2
-rw-r--r--src/script/lua_api/l_noise.h4
-rw-r--r--src/script/lua_api/l_object.cpp175
-rw-r--r--src/script/lua_api/l_object.h20
-rw-r--r--src/script/lua_api/l_particles.cpp35
-rw-r--r--src/script/lua_api/l_server.cpp31
-rw-r--r--src/script/lua_api/l_server.h3
-rw-r--r--src/script/lua_api/l_settings.cpp13
-rw-r--r--src/script/lua_api/l_settings.h3
-rw-r--r--src/script/lua_api/l_util.cpp109
-rw-r--r--src/script/lua_api/l_util.h12
-rw-r--r--src/script/lua_api/l_vmanip.cpp10
37 files changed, 816 insertions, 262 deletions
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index 06e20c2a0..541744895 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "porting.h"
#include "mg_schematic.h"
#include "noise.h"
-#include "json/json.h"
+#include <json/json.h>
struct EnumString es_TileAnimationType[] =
{
@@ -65,9 +65,8 @@ ItemDefinition read_item_definition(lua_State* L,int index,
}
lua_pop(L, 1);
- def.stack_max = getintfield_default(L, index, "stack_max", def.stack_max);
- if(def.stack_max == 0)
- def.stack_max = 1;
+ int stack_max = getintfield_default(L, index, "stack_max", def.stack_max);
+ def.stack_max = rangelim(stack_max, 1, U16_MAX);
lua_getfield(L, index, "on_use");
def.usable = lua_isfunction(L, -1);
@@ -527,6 +526,12 @@ ContentFeatures read_content_features(lua_State *L, int index)
// Amount of light the node emits
f.light_source = getintfield_default(L, index,
"light_source", f.light_source);
+ if (f.light_source > LIGHT_MAX) {
+ warningstream << "Node " << f.name.c_str()
+ << " had greater light_source than " << LIGHT_MAX
+ << ", it was reduced." << std::endl;
+ f.light_source = LIGHT_MAX;
+ }
f.damage_per_second = getintfield_default(L, index,
"damage_per_second", f.damage_per_second);
@@ -830,20 +835,18 @@ void push_tool_capabilities(lua_State *L,
// Create groupcaps table
lua_newtable(L);
// For each groupcap
- for(std::map<std::string, ToolGroupCap>::const_iterator
- i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){
+ for (ToolGCMap::const_iterator i = toolcap.groupcaps.begin();
+ i != toolcap.groupcaps.end(); i++) {
// Create groupcap table
lua_newtable(L);
const std::string &name = i->first;
const ToolGroupCap &groupcap = i->second;
// Create subtable "times"
lua_newtable(L);
- for(std::map<int, float>::const_iterator
- i = groupcap.times.begin(); i != groupcap.times.end(); i++){
- int rating = i->first;
- float time = i->second;
- lua_pushinteger(L, rating);
- lua_pushnumber(L, time);
+ for (UNORDERED_MAP<int, float>::const_iterator
+ i = groupcap.times.begin(); i != groupcap.times.end(); i++) {
+ lua_pushinteger(L, i->first);
+ lua_pushnumber(L, i->second);
lua_settable(L, -3);
}
// Set subtable "times"
@@ -859,8 +862,8 @@ void push_tool_capabilities(lua_State *L,
//Create damage_groups table
lua_newtable(L);
// For each damage group
- for(std::map<std::string, s16>::const_iterator
- i = toolcap.damageGroups.begin(); i != toolcap.damageGroups.end(); i++){
+ for (DamageGroup::const_iterator i = toolcap.damageGroups.begin();
+ i != toolcap.damageGroups.end(); i++) {
// Create damage group table
lua_pushinteger(L, i->second);
lua_setfield(L, -2, i->first.c_str());
@@ -1066,8 +1069,7 @@ void push_flags_string(lua_State *L, FlagDesc *flagdesc, u32 flags, u32 flagmask
/******************************************************************************/
/******************************************************************************/
-void read_groups(lua_State *L, int index,
- std::map<std::string, int> &result)
+void read_groups(lua_State *L, int index, ItemGroupList &result)
{
if (!lua_istable(L,index))
return;
@@ -1086,11 +1088,10 @@ void read_groups(lua_State *L, int index,
}
/******************************************************************************/
-void push_groups(lua_State *L, const std::map<std::string, int> &groups)
+void push_groups(lua_State *L, const ItemGroupList &groups)
{
lua_newtable(L);
- std::map<std::string, int>::const_iterator it;
- for (it = groups.begin(); it != groups.end(); ++it) {
+ for (ItemGroupList::const_iterator it = groups.begin(); it != groups.end(); ++it) {
lua_pushnumber(L, it->second);
lua_setfield(L, -2, it->first.c_str());
}
@@ -1250,8 +1251,13 @@ static bool push_json_value_helper(lua_State *L, const Json::Value &value,
lua_newtable(L);
for (Json::Value::const_iterator it = value.begin();
it != value.end(); ++it) {
+#ifndef JSONCPP_STRING
const char *str = it.memberName();
lua_pushstring(L, str ? str : "");
+#else
+ std::string str = it.name();
+ lua_pushstring(L, str.c_str());
+#endif
push_json_value_helper(L, *it, nullindex);
lua_rawset(L, -3);
}
diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h
index 46416ad8e..2a2228b6d 100644
--- a/src/script/common/c_content.h
+++ b/src/script/common/c_content.h
@@ -33,11 +33,11 @@ extern "C" {
}
#include <iostream>
-#include <map>
#include <vector>
#include "irrlichttypes_bloated.h"
#include "util/string.h"
+#include "itemgroup.h"
namespace Json { class Value; }
@@ -106,10 +106,10 @@ void pushnode (lua_State *L, const MapNode &n,
NodeBox read_nodebox (lua_State *L, int index);
void read_groups (lua_State *L, int index,
- std::map<std::string, int> &result);
+ ItemGroupList &result);
void push_groups (lua_State *L,
- const std::map<std::string, int> &groups);
+ const ItemGroupList &groups);
//TODO rename to "read_enum_field"
int getenumfield (lua_State *L, int table,
diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp
index 55c4a5f5a..f36298915 100644
--- a/src/script/common/c_converter.cpp
+++ b/src/script/common/c_converter.cpp
@@ -23,6 +23,7 @@ extern "C" {
}
#include "util/numeric.h"
+#include "util/serialize.h"
#include "util/string.h"
#include "common/c_converter.h"
#include "constants.h"
@@ -37,6 +38,14 @@ extern "C" {
} \
} while(0)
#define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER)
+#define CHECK_FLOAT_RANGE(value, name) \
+if (value < F1000_MIN || value > F1000_MAX) { \
+ std::ostringstream error_text; \
+ error_text << "Invalid float vector dimension range '" name "' " << \
+ "(expected " << F1000_MIN << " < " name " < " << F1000_MAX << \
+ " got " << value << ")." << std::endl; \
+ throw LuaError(error_text.str()); \
+}
#define CHECK_POS_TAB(index) CHECK_TYPE(index, "position", LUA_TTABLE)
@@ -170,14 +179,17 @@ v3f check_v3f(lua_State *L, int index)
lua_getfield(L, index, "x");
CHECK_POS_COORD("x");
pos.X = lua_tonumber(L, -1);
+ CHECK_FLOAT_RANGE(pos.X, "x")
lua_pop(L, 1);
lua_getfield(L, index, "y");
CHECK_POS_COORD("y");
pos.Y = lua_tonumber(L, -1);
+ CHECK_FLOAT_RANGE(pos.Y, "y")
lua_pop(L, 1);
lua_getfield(L, index, "z");
CHECK_POS_COORD("z");
pos.Z = lua_tonumber(L, -1);
+ CHECK_FLOAT_RANGE(pos.Z, "z")
lua_pop(L, 1);
return pos;
}
@@ -391,7 +403,7 @@ bool getintfield(lua_State *L, int table,
lua_getfield(L, table, fieldname);
bool got = false;
if(lua_isnumber(L, -1)){
- result = lua_tonumber(L, -1);
+ result = lua_tointeger(L, -1);
got = true;
}
lua_pop(L, 1);
@@ -404,7 +416,7 @@ bool getintfield(lua_State *L, int table,
lua_getfield(L, table, fieldname);
bool got = false;
if(lua_isnumber(L, -1)){
- result = lua_tonumber(L, -1);
+ result = lua_tointeger(L, -1);
got = true;
}
lua_pop(L, 1);
@@ -417,7 +429,7 @@ bool getintfield(lua_State *L, int table,
lua_getfield(L, table, fieldname);
bool got = false;
if(lua_isnumber(L, -1)){
- result = lua_tonumber(L, -1);
+ result = lua_tointeger(L, -1);
got = true;
}
lua_pop(L, 1);
@@ -430,7 +442,7 @@ bool getintfield(lua_State *L, int table,
lua_getfield(L, table, fieldname);
bool got = false;
if(lua_isnumber(L, -1)){
- result = lua_tonumber(L, -1);
+ result = lua_tointeger(L, -1);
got = true;
}
lua_pop(L, 1);
diff --git a/src/script/common/c_converter.h b/src/script/common/c_converter.h
index eefac0ed7..a5fbee765 100644
--- a/src/script/common/c_converter.h
+++ b/src/script/common/c_converter.h
@@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define C_CONVERTER_H_
#include <vector>
-#include <map>
+#include "util/cpp11_container.h"
#include "irrlichttypes_bloated.h"
#include "common/c_types.h"
@@ -60,7 +60,7 @@ bool getintfield(lua_State *L, int table,
bool getintfield(lua_State *L, int table,
const char *fieldname, u32 &result);
void read_groups(lua_State *L, int index,
- std::map<std::string, int> &result);
+ UNORDERED_MAP<std::string, int> &result);
bool getboolfield(lua_State *L, int table,
const char *fieldname, bool &result);
bool getfloatfield(lua_State *L, int table,
diff --git a/src/script/cpp_api/s_async.cpp b/src/script/cpp_api/s_async.cpp
index 9bf3fcf49..1fb84fab6 100644
--- a/src/script/cpp_api/s_async.cpp
+++ b/src/script/cpp_api/s_async.cpp
@@ -81,6 +81,7 @@ bool AsyncEngine::registerFunction(const char* name, lua_CFunction func)
if (initDone) {
return false;
}
+
functionList[name] = func;
return true;
}
@@ -203,7 +204,7 @@ void AsyncEngine::pushFinishedJobs(lua_State* L) {
/******************************************************************************/
void AsyncEngine::prepareEnvironment(lua_State* L, int top)
{
- for (std::map<std::string, lua_CFunction>::iterator it = functionList.begin();
+ for (UNORDERED_MAP<std::string, lua_CFunction>::iterator it = functionList.begin();
it != functionList.end(); it++) {
lua_pushstring(L, it->first.c_str());
lua_pushcfunction(L, it->second);
diff --git a/src/script/cpp_api/s_async.h b/src/script/cpp_api/s_async.h
index 8d612d58c..016381e5f 100644
--- a/src/script/cpp_api/s_async.h
+++ b/src/script/cpp_api/s_async.h
@@ -132,7 +132,7 @@ private:
bool initDone;
// Internal store for registred functions
- std::map<std::string, lua_CFunction> functionList;
+ UNORDERED_MAP<std::string, lua_CFunction> functionList;
// Internal counter to create job IDs
unsigned int jobIdCounter;
diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp
index 82d0d4f0e..913d8539d 100644
--- a/src/script/cpp_api/s_env.cpp
+++ b/src/script/cpp_api/s_env.cpp
@@ -212,11 +212,13 @@ void ScriptApiEnv::on_emerge_area_completion(
{
Server *server = getServer();
+ // This function should be executed with envlock held.
+ // The caller (LuaEmergeAreaCallback in src/script/lua_api/l_env.cpp)
+ // should have obtained the lock.
// Note that the order of these locks is important! Envlock must *ALWAYS*
// be acquired before attempting to acquire scriptlock, or else ServerThread
// will try to acquire scriptlock after it already owns envlock, thus
// deadlocking EmergeThread and ServerThread
- MutexAutoLock envlock(server->m_env_mutex);
SCRIPTAPI_PRECHECKHEADER
diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp
index 17f0f0dac..379ed773f 100644
--- a/src/script/cpp_api/s_node.cpp
+++ b/src/script/cpp_api/s_node.cpp
@@ -58,6 +58,7 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] =
{CPT2_WALLMOUNTED, "wallmounted"},
{CPT2_LEVELED, "leveled"},
{CPT2_DEGROTATE, "degrotate"},
+ {CPT2_MESHOPTIONS, "meshoptions"},
{0, NULL},
};
diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp
index 807430678..a8c07476c 100644
--- a/src/script/cpp_api/s_player.cpp
+++ b/src/script/cpp_api/s_player.cpp
@@ -135,7 +135,8 @@ void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player)
runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
}
-void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player)
+void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player,
+ bool timeout)
{
SCRIPTAPI_PRECHECKHEADER
@@ -144,7 +145,8 @@ void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player)
lua_getfield(L, -1, "registered_on_leaveplayers");
// Call callbacks
objectrefGetOrCreate(L, player);
- runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+ lua_pushboolean(L, timeout);
+ runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
}
void ScriptApiPlayer::on_cheat(ServerActiveObject *player,
diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h
index 2e4dc2222..86ee1b024 100644
--- a/src/script/cpp_api/s_player.h
+++ b/src/script/cpp_api/s_player.h
@@ -38,7 +38,7 @@ public:
bool on_prejoinplayer(const std::string &name, const std::string &ip,
std::string *reason);
void on_joinplayer(ServerActiveObject *player);
- void on_leaveplayer(ServerActiveObject *player);
+ void on_leaveplayer(ServerActiveObject *player, bool timeout);
void on_cheat(ServerActiveObject *player, const std::string &cheat_type);
bool on_punchplayer(ServerActiveObject *player,
ServerActiveObject *hitter, float time_from_last_punch,
diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp
index 730235c7b..1b1f148cd 100644
--- a/src/script/cpp_api/s_security.cpp
+++ b/src/script/cpp_api/s_security.cpp
@@ -249,8 +249,8 @@ bool ScriptApiSecurity::isSecure(lua_State *L)
#define CHECK_FILE_ERR(ret, fp) \
if (ret) { \
- if (fp) std::fclose(fp); \
lua_pushfstring(L, "%s: %s", path, strerror(errno)); \
+ if (fp) std::fclose(fp); \
return false; \
}
@@ -285,39 +285,50 @@ bool ScriptApiSecurity::safeLoadFile(lua_State *L, const char *path)
if (c == LUA_SIGNATURE[0]) {
lua_pushliteral(L, "Bytecode prohibited when mod security is enabled.");
+ std::fclose(fp);
+ if (path) {
+ delete [] chunk_name;
+ }
return false;
}
// Read the file
int ret = std::fseek(fp, 0, SEEK_END);
CHECK_FILE_ERR(ret, fp);
- if (ret) {
- std::fclose(fp);
- lua_pushfstring(L, "%s: %s", path, strerror(errno));
- return false;
- }
+
size_t size = std::ftell(fp) - start;
char *code = new char[size];
ret = std::fseek(fp, start, SEEK_SET);
- CHECK_FILE_ERR(ret, fp);
if (ret) {
- std::fclose(fp);
lua_pushfstring(L, "%s: %s", path, strerror(errno));
+ std::fclose(fp);
+ delete [] code;
+ if (path) {
+ delete [] chunk_name;
+ }
return false;
}
+
size_t num_read = std::fread(code, 1, size, fp);
if (path) {
std::fclose(fp);
}
if (num_read != size) {
lua_pushliteral(L, "Error reading file to load.");
+ delete [] code;
+ if (path) {
+ delete [] chunk_name;
+ }
return false;
}
if (luaL_loadbuffer(L, code, size, chunk_name)) {
+ delete [] code;
return false;
}
+ delete [] code;
+
if (path) {
delete [] chunk_name;
}
@@ -325,12 +336,15 @@ bool ScriptApiSecurity::safeLoadFile(lua_State *L, const char *path)
}
-bool ScriptApiSecurity::checkPath(lua_State *L, const char *path)
+bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
+ bool write_required, bool *write_allowed)
{
+ if (write_allowed)
+ *write_allowed = false;
+
std::string str; // Transient
- std::string norel_path = fs::RemoveRelativePathComponents(path);
- std::string abs_path = fs::AbsolutePath(norel_path);
+ std::string abs_path = fs::AbsolutePath(path);
if (!abs_path.empty()) {
// Don't allow accessing the settings file
@@ -341,18 +355,29 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path)
// If we couldn't find the absolute path (path doesn't exist) then
// try removing the last components until it works (to allow
// non-existent files/folders for mkdir).
- std::string cur_path = norel_path;
+ std::string cur_path = path;
std::string removed;
while (abs_path.empty() && !cur_path.empty()) {
- std::string tmp_rmed;
- cur_path = fs::RemoveLastPathComponent(cur_path, &tmp_rmed);
- removed = tmp_rmed + (removed.empty() ? "" : DIR_DELIM + removed);
+ std::string component;
+ cur_path = fs::RemoveLastPathComponent(cur_path, &component);
+ if (component == "..") {
+ // Parent components can't be allowed or we could allow something like
+ // /home/user/minetest/worlds/foo/noexist/../../../../../../etc/passwd.
+ // If we have previous non-relative elements in the path we might be
+ // able to remove them so that things like worlds/foo/noexist/../auth.txt
+ // could be allowed, but those paths will be interpreted as nonexistent
+ // by the operating system anyways.
+ return false;
+ }
+ removed = component + (removed.empty() ? "" : DIR_DELIM + removed);
abs_path = fs::AbsolutePath(cur_path);
}
- if (abs_path.empty()) return false;
+ if (abs_path.empty())
+ return false;
// Add the removed parts back so that you can't, eg, create a
// directory in worldmods if worldmods doesn't exist.
- if (!removed.empty()) abs_path += DIR_DELIM + removed;
+ if (!removed.empty())
+ abs_path += DIR_DELIM + removed;
// Get server from registry
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
@@ -369,32 +394,53 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path)
// Builtin can access anything
if (mod_name == BUILTIN_MOD_NAME) {
+ if (write_allowed) *write_allowed = true;
return true;
}
// Allow paths in mod path
- const ModSpec *mod = server->getModSpec(mod_name);
- if (mod) {
- str = fs::AbsolutePath(mod->path);
+ // Don't bother if write access isn't important, since it will be handled later
+ if (write_required || write_allowed != NULL) {
+ const ModSpec *mod = server->getModSpec(mod_name);
+ if (mod) {
+ str = fs::AbsolutePath(mod->path);
+ if (!str.empty() && fs::PathStartsWith(abs_path, str)) {
+ if (write_allowed) *write_allowed = true;
+ return true;
+ }
+ }
+ }
+ }
+ lua_pop(L, 1); // Pop mod name
+
+ // Allow read-only access to all mod directories
+ if (!write_required) {
+ const std::vector<ModSpec> mods = server->getMods();
+ for (size_t i = 0; i < mods.size(); ++i) {
+ str = fs::AbsolutePath(mods[i].path);
if (!str.empty() && fs::PathStartsWith(abs_path, str)) {
return true;
}
}
}
- lua_pop(L, 1); // Pop mod name
str = fs::AbsolutePath(server->getWorldPath());
- if (str.empty()) return false;
- // Don't allow access to world mods. We add to the absolute path
- // of the world instead of getting the absolute paths directly
- // because that won't work if they don't exist.
- if (fs::PathStartsWith(abs_path, str + DIR_DELIM + "worldmods") ||
- fs::PathStartsWith(abs_path, str + DIR_DELIM + "game")) {
- return false;
- }
- // Allow all other paths in world path
- if (fs::PathStartsWith(abs_path, str)) {
- return true;
+ if (!str.empty()) {
+ // Don't allow access to other paths in the world mod/game path.
+ // These have to be blocked so you can't override a trusted mod
+ // by creating a mod with the same name in a world mod directory.
+ // We add to the absolute path of the world instead of getting
+ // the absolute paths directly because that won't work if they
+ // don't exist.
+ if (fs::PathStartsWith(abs_path, str + DIR_DELIM + "worldmods") ||
+ fs::PathStartsWith(abs_path, str + DIR_DELIM + "game")) {
+ return false;
+ }
+ // Allow all other paths in world path
+ if (fs::PathStartsWith(abs_path, str)) {
+ if (write_allowed) *write_allowed = true;
+ return true;
+ }
}
// Default to disallowing
@@ -465,7 +511,7 @@ int ScriptApiSecurity::sl_g_loadfile(lua_State *L)
if (lua_isstring(L, 1)) {
path = lua_tostring(L, 1);
- CHECK_SECURE_PATH(L, path);
+ CHECK_SECURE_PATH_INTERNAL(L, path, false, NULL);
}
if (!safeLoadFile(L, path)) {
@@ -514,14 +560,28 @@ int ScriptApiSecurity::sl_g_require(lua_State *L)
int ScriptApiSecurity::sl_io_open(lua_State *L)
{
+ bool with_mode = lua_gettop(L) > 1;
+
luaL_checktype(L, 1, LUA_TSTRING);
const char *path = lua_tostring(L, 1);
- CHECK_SECURE_PATH(L, path);
+
+ bool write_requested = false;
+ if (with_mode) {
+ luaL_checktype(L, 2, LUA_TSTRING);
+ const char *mode = lua_tostring(L, 2);
+ write_requested = strchr(mode, 'w') != NULL ||
+ strchr(mode, '+') != NULL ||
+ strchr(mode, 'a') != NULL;
+ }
+ CHECK_SECURE_PATH_INTERNAL(L, path, write_requested, NULL);
push_original(L, "io", "open");
lua_pushvalue(L, 1);
- lua_pushvalue(L, 2);
- lua_call(L, 2, 2);
+ if (with_mode) {
+ lua_pushvalue(L, 2);
+ }
+
+ lua_call(L, with_mode ? 2 : 1, 2);
return 2;
}
@@ -530,7 +590,7 @@ int ScriptApiSecurity::sl_io_input(lua_State *L)
{
if (lua_isstring(L, 1)) {
const char *path = lua_tostring(L, 1);
- CHECK_SECURE_PATH(L, path);
+ CHECK_SECURE_PATH_INTERNAL(L, path, false, NULL);
}
push_original(L, "io", "input");
@@ -544,7 +604,7 @@ int ScriptApiSecurity::sl_io_output(lua_State *L)
{
if (lua_isstring(L, 1)) {
const char *path = lua_tostring(L, 1);
- CHECK_SECURE_PATH(L, path);
+ CHECK_SECURE_PATH_INTERNAL(L, path, true, NULL);
}
push_original(L, "io", "output");
@@ -558,16 +618,16 @@ int ScriptApiSecurity::sl_io_lines(lua_State *L)
{
if (lua_isstring(L, 1)) {
const char *path = lua_tostring(L, 1);
- CHECK_SECURE_PATH(L, path);
+ CHECK_SECURE_PATH_INTERNAL(L, path, false, NULL);
}
+ int top_precall = lua_gettop(L);
push_original(L, "io", "lines");
lua_pushvalue(L, 1);
- int top_precall = lua_gettop(L);
lua_call(L, 1, LUA_MULTRET);
// Return number of arguments returned by the function,
// adjusting for the function being poped.
- return lua_gettop(L) - (top_precall - 1);
+ return lua_gettop(L) - top_precall;
}
@@ -575,11 +635,11 @@ int ScriptApiSecurity::sl_os_rename(lua_State *L)
{
luaL_checktype(L, 1, LUA_TSTRING);
const char *path1 = lua_tostring(L, 1);
- CHECK_SECURE_PATH(L, path1);
+ CHECK_SECURE_PATH_INTERNAL(L, path1, true, NULL);
luaL_checktype(L, 2, LUA_TSTRING);
const char *path2 = lua_tostring(L, 2);
- CHECK_SECURE_PATH(L, path2);
+ CHECK_SECURE_PATH_INTERNAL(L, path2, true, NULL);
push_original(L, "os", "rename");
lua_pushvalue(L, 1);
@@ -593,7 +653,7 @@ int ScriptApiSecurity::sl_os_remove(lua_State *L)
{
luaL_checktype(L, 1, LUA_TSTRING);
const char *path = lua_tostring(L, 1);
- CHECK_SECURE_PATH(L, path);
+ CHECK_SECURE_PATH_INTERNAL(L, path, true, NULL);
push_original(L, "os", "remove");
lua_pushvalue(L, 1);
diff --git a/src/script/cpp_api/s_security.h b/src/script/cpp_api/s_security.h
index 97bc5c067..6876108e8 100644
--- a/src/script/cpp_api/s_security.h
+++ b/src/script/cpp_api/s_security.h
@@ -23,14 +23,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "cpp_api/s_base.h"
-#define CHECK_SECURE_PATH(L, path) \
- if (!ScriptApiSecurity::checkPath(L, path)) { \
- throw LuaError(std::string("Attempt to access external file ") + \
- path + " with mod security on."); \
+#define CHECK_SECURE_PATH_INTERNAL(L, path, write_required, ptr) \
+ if (!ScriptApiSecurity::checkPath(L, path, write_required, ptr)) { \
+ throw LuaError(std::string("Mod security: Blocked attempted ") + \
+ (write_required ? "write to " : "read from ") + path); \
}
-#define CHECK_SECURE_PATH_OPTIONAL(L, path) \
+#define CHECK_SECURE_PATH(L, path, write_required) \
if (ScriptApiSecurity::isSecure(L)) { \
- CHECK_SECURE_PATH(L, path); \
+ CHECK_SECURE_PATH_INTERNAL(L, path, write_required, NULL); \
+ }
+#define CHECK_SECURE_PATH_POSSIBLE_WRITE(L, path, ptr) \
+ if (ScriptApiSecurity::isSecure(L)) { \
+ CHECK_SECURE_PATH_INTERNAL(L, path, false, ptr); \
}
@@ -43,8 +47,9 @@ public:
static bool isSecure(lua_State *L);
// Loads a file as Lua code safely (doesn't allow bytecode).
static bool safeLoadFile(lua_State *L, const char *path);
- // Checks if mods are allowed to read and write to the path
- static bool checkPath(lua_State *L, const char *path);
+ // Checks if mods are allowed to read (and optionally write) to the path
+ static bool checkPath(lua_State *L, const char *path, bool write_required,
+ bool *write_allowed=NULL);
private:
// Syntax: "sl_" <Library name or 'g' (global)> '_' <Function name>
diff --git a/src/script/lua_api/l_areastore.cpp b/src/script/lua_api/l_areastore.cpp
index 20e7875c7..09a5c78f9 100644
--- a/src/script/lua_api/l_areastore.cpp
+++ b/src/script/lua_api/l_areastore.cpp
@@ -111,6 +111,9 @@ int LuaAreaStore::l_get_area(lua_State *L)
const Area *res;
res = ast->getArea(id);
+ if (!res)
+ return 0;
+
push_area(L, res, include_borders, include_data);
return 1;
@@ -260,7 +263,7 @@ int LuaAreaStore::l_to_file(lua_State *L)
AreaStore *ast = o->as;
const char *filename = luaL_checkstring(L, 2);
- CHECK_SECURE_PATH_OPTIONAL(L, filename);
+ CHECK_SECURE_PATH(L, filename, true);
std::ostringstream os(std::ios_base::binary);
ast->serialize(os);
@@ -291,7 +294,7 @@ int LuaAreaStore::l_from_file(lua_State *L)
LuaAreaStore *o = checkobject(L, 1);
const char *filename = luaL_checkstring(L, 2);
- CHECK_SECURE_PATH_OPTIONAL(L, filename);
+ CHECK_SECURE_PATH(L, filename, false);
std::ifstream is(filename, std::ios::binary);
return deserialization_helper(L, o->as, is);
diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp
index 391a0133d..2236566de 100644
--- a/src/script/lua_api/l_craft.cpp
+++ b/src/script/lua_api/l_craft.cpp
@@ -34,7 +34,6 @@ struct EnumString ModApiCraft::es_CraftMethod[] =
{0, NULL},
};
-
// helper for register_craft
bool ModApiCraft::readCraftRecipeShaped(lua_State *L, int index,
int &width, std::vector<std::string> &recipe)
@@ -281,6 +280,80 @@ int ModApiCraft::l_register_craft(lua_State *L)
return 0; /* number of results */
}
+// clear_craft({[output=item], [recipe={{item00,item10},{item01,item11}}])
+int ModApiCraft::l_clear_craft(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ int table = 1;
+
+ // Get the writable craft definition manager from the server
+ IWritableCraftDefManager *craftdef =
+ getServer(L)->getWritableCraftDefManager();
+
+ std::string output = getstringfield_default(L, table, "output", "");
+ std::string type = getstringfield_default(L, table, "type", "shaped");
+ CraftOutput c_output(output, 0);
+ if (output != "") {
+ if (craftdef->clearCraftRecipesByOutput(c_output, getServer(L)))
+ return 0;
+ else
+ throw LuaError("No craft recipe known for output"
+ " (output=\"" + output + "\")");
+ }
+ std::vector<std::string> recipe;
+ int width = 0;
+ CraftMethod method = CRAFT_METHOD_NORMAL;
+ /*
+ CraftDefinitionShaped
+ */
+ if (type == "shaped") {
+ lua_getfield(L, table, "recipe");
+ if (lua_isnil(L, -1))
+ throw LuaError("Either output or recipe has to be defined");
+ if (!readCraftRecipeShaped(L, -1, width, recipe))
+ throw LuaError("Invalid crafting recipe");
+ }
+ /*
+ CraftDefinitionShapeless
+ */
+ else if (type == "shapeless") {
+ lua_getfield(L, table, "recipe");
+ if (lua_isnil(L, -1))
+ throw LuaError("Either output or recipe has to be defined");
+ if (!readCraftRecipeShapeless(L, -1, recipe))
+ throw LuaError("Invalid crafting recipe");
+ }
+ /*
+ CraftDefinitionCooking
+ */
+ else if (type == "cooking") {
+ method = CRAFT_METHOD_COOKING;
+ std::string rec = getstringfield_default(L, table, "recipe", "");
+ if (rec == "")
+ throw LuaError("Crafting definition (cooking)"
+ " is missing a recipe");
+ recipe.push_back(rec);
+ }
+ /*
+ CraftDefinitionFuel
+ */
+ else if (type == "fuel") {
+ method = CRAFT_METHOD_FUEL;
+ std::string rec = getstringfield_default(L, table, "recipe", "");
+ if (rec == "")
+ throw LuaError("Crafting definition (fuel)"
+ " is missing a recipe");
+ recipe.push_back(rec);
+ } else {
+ throw LuaError("Unknown crafting definition type: \"" + type + "\"");
+ }
+ if (!craftdef->clearCraftRecipesByInput(method, width, recipe, getServer(L)))
+ throw LuaError("No crafting specified for input");
+ lua_pop(L, 1);
+ return 0;
+}
+
// get_craft_result(input)
int ModApiCraft::l_get_craft_result(lua_State *L)
{
@@ -349,20 +422,28 @@ static void push_craft_recipe(lua_State *L, IGameDef *gdef,
}
lua_setfield(L, -2, "items");
setintfield(L, -1, "width", input.width);
+
+ std::string method_s;
switch (input.method) {
case CRAFT_METHOD_NORMAL:
- lua_pushstring(L, "normal");
+ method_s = "normal";
break;
case CRAFT_METHOD_COOKING:
- lua_pushstring(L, "cooking");
+ method_s = "cooking";
break;
case CRAFT_METHOD_FUEL:
- lua_pushstring(L, "fuel");
+ method_s = "fuel";
break;
default:
- lua_pushstring(L, "unknown");
+ method_s = "unknown";
}
+ lua_pushstring(L, method_s.c_str());
+ lua_setfield(L, -2, "method");
+
+ // Deprecated, only for compatibility's sake
+ lua_pushstring(L, method_s.c_str());
lua_setfield(L, -2, "type");
+
lua_pushstring(L, output.item.c_str());
lua_setfield(L, -2, "output");
}
@@ -431,4 +512,5 @@ void ModApiCraft::Initialize(lua_State *L, int top)
API_FCT(get_craft_recipe);
API_FCT(get_craft_result);
API_FCT(register_craft);
+ API_FCT(clear_craft);
}
diff --git a/src/script/lua_api/l_craft.h b/src/script/lua_api/l_craft.h
index 548608776..eb2bce706 100644
--- a/src/script/lua_api/l_craft.h
+++ b/src/script/lua_api/l_craft.h
@@ -33,6 +33,7 @@ private:
static int l_get_craft_recipe(lua_State *L);
static int l_get_all_craft_recipes(lua_State *L);
static int l_get_craft_result(lua_State *L);
+ static int l_clear_craft(lua_State *L);
static bool readCraftReplacements(lua_State *L, int index,
CraftReplacements &replacements);
diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp
index 8284c3fcb..68d10308c 100644
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -137,6 +137,10 @@ void LuaEmergeAreaCallback(v3s16 blockpos, EmergeAction action, void *param)
assert(state->script != NULL);
assert(state->refcount > 0);
+ // state must be protected by envlock
+ Server *server = state->script->getServer();
+ MutexAutoLock envlock(server->m_env_mutex);
+
state->refcount--;
state->script->on_emerge_area_completion(blockpos, action, state);
@@ -494,8 +498,8 @@ int ModApiEnvMod::l_get_player_by_name(lua_State *L)
// Do it
const char *name = luaL_checkstring(L, 1);
- Player *player = env->getPlayer(name);
- if(player == NULL){
+ RemotePlayer *player = dynamic_cast<RemotePlayer *>(env->getPlayer(name));
+ if (player == NULL){
lua_pushnil(L);
return 1;
}
@@ -758,7 +762,7 @@ int ModApiEnvMod::l_get_perlin_map(lua_State *L)
return 0;
v3s16 size = read_v3s16(L, 2);
- int seed = (int)(env->getServerMap().getSeed());
+ s32 seed = (s32)(env->getServerMap().getSeed());
LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(&np, seed, size);
*(void **)(lua_newuserdata(L, sizeof(void *))) = n;
luaL_getmetatable(L, "PerlinNoiseMap");
diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp
index de9f9374a..38eade609 100644
--- a/src/script/lua_api/l_inventory.cpp
+++ b/src/script/lua_api/l_inventory.cpp
@@ -420,7 +420,7 @@ void InvRef::create(lua_State *L, const InventoryLocation &loc)
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
}
-void InvRef::createPlayer(lua_State *L, Player *player)
+void InvRef::createPlayer(lua_State *L, RemotePlayer *player)
{
NO_MAP_LOCK_REQUIRED;
InventoryLocation loc;
@@ -520,16 +520,17 @@ int ModApiInventory::l_get_inventory(lua_State *L)
}
}
-// create_detached_inventory_raw(name)
+// create_detached_inventory_raw(name, [player_name])
int ModApiInventory::l_create_detached_inventory_raw(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
const char *name = luaL_checkstring(L, 1);
- if(getServer(L)->createDetachedInventory(name) != NULL){
+ const char *player = lua_isstring(L, 2) ? lua_tostring(L, 2) : "";
+ if (getServer(L)->createDetachedInventory(name, player) != NULL) {
InventoryLocation loc;
loc.setDetached(name);
InvRef::create(L, loc);
- }else{
+ } else {
lua_pushnil(L);
}
return 1;
diff --git a/src/script/lua_api/l_inventory.h b/src/script/lua_api/l_inventory.h
index 2d4b29d0c..cc5333965 100644
--- a/src/script/lua_api/l_inventory.h
+++ b/src/script/lua_api/l_inventory.h
@@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "inventory.h"
#include "inventorymanager.h"
-class Player;
+class RemotePlayer;
/*
InvRef
@@ -112,7 +112,7 @@ public:
// Creates an InvRef and leaves it on top of stack
// Not callable from Lua; all references are created on the C side.
static void create(lua_State *L, const InventoryLocation &loc);
- static void createPlayer(lua_State *L, Player *player);
+ static void createPlayer(lua_State *L, RemotePlayer *player);
static void createNodeMeta(lua_State *L, v3s16 p);
static void Register(lua_State *L);
};
@@ -123,11 +123,6 @@ private:
static int l_get_inventory(lua_State *L);
- static void inventory_set_list_from_lua(Inventory *inv, const char *name,
- lua_State *L, int tableindex, int forcesize);
- static void inventory_get_list_to_lua(Inventory *inv, const char *name,
- lua_State *L);
-
public:
static void Initialize(lua_State *L, int top);
};
diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp
index 5381cba76..ff0baea14 100644
--- a/src/script/lua_api/l_item.cpp
+++ b/src/script/lua_api/l_item.cpp
@@ -525,6 +525,27 @@ int ModApiItemMod::l_register_item_raw(lua_State *L)
return 0; /* number of results */
}
+// unregister_item(name)
+int ModApiItemMod::l_unregister_item_raw(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ std::string name = luaL_checkstring(L, 1);
+
+ IWritableItemDefManager *idef =
+ getServer(L)->getWritableItemDefManager();
+
+ // Unregister the node
+ if (idef->get(name).type == ITEM_NODE) {
+ IWritableNodeDefManager *ndef =
+ getServer(L)->getWritableNodeDefManager();
+ ndef->removeNode(name);
+ }
+
+ idef->unregisterItem(name);
+
+ return 0; /* number of results */
+}
+
// register_alias_raw(name, convert_to_name)
int ModApiItemMod::l_register_alias_raw(lua_State *L)
{
@@ -570,6 +591,7 @@ int ModApiItemMod::l_get_name_from_content_id(lua_State *L)
void ModApiItemMod::Initialize(lua_State *L, int top)
{
API_FCT(register_item_raw);
+ API_FCT(unregister_item_raw);
API_FCT(register_alias_raw);
API_FCT(get_content_id);
API_FCT(get_name_from_content_id);
diff --git a/src/script/lua_api/l_item.h b/src/script/lua_api/l_item.h
index 0f9e4ba9b..be919b701 100644
--- a/src/script/lua_api/l_item.h
+++ b/src/script/lua_api/l_item.h
@@ -135,6 +135,7 @@ public:
class ModApiItemMod : public ModApiBase {
private:
static int l_register_item_raw(lua_State *L);
+ static int l_unregister_item_raw(lua_State *L);
static int l_register_alias_raw(lua_State *L);
static int l_get_content_id(lua_State *L);
static int l_get_name_from_content_id(lua_State *L);
diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp
index 7b29db159..4a2484613 100644
--- a/src/script/lua_api/l_mainmenu.cpp
+++ b/src/script/lua_api/l_mainmenu.cpp
@@ -31,7 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "filesys.h"
#include "convert_json.h"
#include "serverlist.h"
-#include "emerge.h"
+#include "mapgen.h"
#include "sound.h"
#include "settings.h"
#include "log.h"
@@ -707,7 +707,7 @@ int ModApiMainMenu::l_set_topleft_text(lua_State *L)
int ModApiMainMenu::l_get_mapgen_names(lua_State *L)
{
std::vector<const char *> names;
- EmergeManager::getMapgenNames(&names, lua_toboolean(L, 1));
+ Mapgen::getMapgenNames(&names, lua_toboolean(L, 1));
lua_newtable(L);
for (size_t i = 0; i != names.size(); i++) {
@@ -956,13 +956,6 @@ int ModApiMainMenu::l_show_file_open_dialog(lua_State *L)
}
/******************************************************************************/
-int ModApiMainMenu::l_get_version(lua_State *L)
-{
- lua_pushstring(L, g_version_string);
- return 1;
-}
-
-/******************************************************************************/
int ModApiMainMenu::l_sound_play(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
@@ -1157,7 +1150,6 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
API_FCT(extract_zip);
API_FCT(get_mainmenu_path);
API_FCT(show_file_open_dialog);
- API_FCT(get_version);
API_FCT(download_file);
API_FCT(get_modstore_details);
API_FCT(get_modstore_list);
@@ -1188,7 +1180,6 @@ void ModApiMainMenu::InitializeAsync(AsyncEngine& engine)
ASYNC_API_FCT(delete_dir);
ASYNC_API_FCT(copy_dir);
//ASYNC_API_FCT(extract_zip); //TODO remove dependency to GuiEngine
- ASYNC_API_FCT(get_version);
ASYNC_API_FCT(download_file);
ASYNC_API_FCT(get_modstore_details);
ASYNC_API_FCT(get_modstore_list);
diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h
index 405af25e8..ad5155ac6 100644
--- a/src/script/lua_api/l_mainmenu.h
+++ b/src/script/lua_api/l_mainmenu.h
@@ -79,8 +79,6 @@ private:
static int l_delete_favorite(lua_State *L);
- static int l_get_version(lua_State *L);
-
static int l_sound_play(lua_State *L);
static int l_sound_stop(lua_State *L);
diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp
index fb839176b..bc1c32f03 100644
--- a/src/script/lua_api/l_mapgen.cpp
+++ b/src/script/lua_api/l_mapgen.cpp
@@ -39,11 +39,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
struct EnumString ModApiMapgen::es_BiomeTerrainType[] =
{
- {BIOME_NORMAL, "normal"},
- {BIOME_LIQUID, "liquid"},
- {BIOME_NETHER, "nether"},
- {BIOME_AETHER, "aether"},
- {BIOME_FLAT, "flat"},
+ {BIOMETYPE_NORMAL, "normal"},
+ {BIOMETYPE_LIQUID, "liquid"},
+ {BIOMETYPE_NETHER, "nether"},
+ {BIOMETYPE_AETHER, "aether"},
+ {BIOMETYPE_FLAT, "flat"},
{0, NULL},
};
@@ -100,7 +100,7 @@ Biome *get_or_load_biome(lua_State *L, int index,
BiomeManager *biomemgr);
Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef);
size_t get_biome_list(lua_State *L, int index,
- BiomeManager *biomemgr, std::set<u8> *biome_id_list);
+ BiomeManager *biomemgr, UNORDERED_SET<u8> *biome_id_list);
Schematic *get_or_load_schematic(lua_State *L, int index,
SchematicManager *schemmgr, StringMap *replace_names);
@@ -244,7 +244,7 @@ bool read_schematic_def(lua_State *L, int index,
schem->schemdata = new MapNode[numnodes];
size_t names_base = names->size();
- std::map<std::string, content_t> name_id_map;
+ UNORDERED_MAP<std::string, content_t> name_id_map;
u32 i = 0;
for (lua_pushnil(L); lua_next(L, -2); i++, lua_pop(L, 1)) {
@@ -266,7 +266,7 @@ bool read_schematic_def(lua_State *L, int index,
u8 param2 = getintfield_default(L, -1, "param2", 0);
//// Find or add new nodename-to-ID mapping
- std::map<std::string, content_t>::iterator it = name_id_map.find(name);
+ UNORDERED_MAP<std::string, content_t>::iterator it = name_id_map.find(name);
content_t name_index;
if (it != name_id_map.end()) {
name_index = it->second;
@@ -371,13 +371,14 @@ Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef)
return NULL;
BiomeType biometype = (BiomeType)getenumfield(L, index, "type",
- ModApiMapgen::es_BiomeTerrainType, BIOME_NORMAL);
+ ModApiMapgen::es_BiomeTerrainType, BIOMETYPE_NORMAL);
Biome *b = BiomeManager::create(biometype);
b->name = getstringfield_default(L, index, "name", "");
b->depth_top = getintfield_default(L, index, "depth_top", 0);
b->depth_filler = getintfield_default(L, index, "depth_filler", -31000);
b->depth_water_top = getintfield_default(L, index, "depth_water_top", 0);
+ b->depth_riverbed = getintfield_default(L, index, "depth_riverbed", 0);
b->y_min = getintfield_default(L, index, "y_min", -31000);
b->y_max = getintfield_default(L, index, "y_max", 31000);
b->heat_point = getfloatfield_default(L, index, "heat_point", 0.f);
@@ -391,6 +392,7 @@ Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef)
nn.push_back(getstringfield_default(L, index, "node_water_top", ""));
nn.push_back(getstringfield_default(L, index, "node_water", ""));
nn.push_back(getstringfield_default(L, index, "node_river_water", ""));
+ nn.push_back(getstringfield_default(L, index, "node_riverbed", ""));
nn.push_back(getstringfield_default(L, index, "node_dust", ""));
ndef->pendNodeResolve(b);
@@ -399,7 +401,7 @@ Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef)
size_t get_biome_list(lua_State *L, int index,
- BiomeManager *biomemgr, std::set<u8> *biome_id_list)
+ BiomeManager *biomemgr, UNORDERED_SET<u8> *biome_id_list)
{
if (index < 0)
index = lua_gettop(L) + 1 + index;
@@ -528,24 +530,26 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
return 1;
}
case MGOBJ_BIOMEMAP: {
- if (!mg->biomemap)
+ if (!mg->biomegen)
return 0;
lua_newtable(L);
for (size_t i = 0; i != maplen; i++) {
- lua_pushinteger(L, mg->biomemap[i]);
+ lua_pushinteger(L, mg->biomegen->biomemap[i]);
lua_rawseti(L, -2, i + 1);
}
return 1;
}
case MGOBJ_HEATMAP: {
- if (!mg->heatmap)
+ if (!mg->biomegen || mg->biomegen->getType() != BIOMEGEN_ORIGINAL)
return 0;
+ BiomeGenOriginal *bg = (BiomeGenOriginal *)mg->biomegen;
+
lua_newtable(L);
for (size_t i = 0; i != maplen; i++) {
- lua_pushnumber(L, mg->heatmap[i]);
+ lua_pushnumber(L, bg->heatmap[i]);
lua_rawseti(L, -2, i + 1);
}
@@ -553,12 +557,14 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
}
case MGOBJ_HUMIDMAP: {
- if (!mg->humidmap)
+ if (!mg->biomegen || mg->biomegen->getType() != BIOMEGEN_ORIGINAL)
return 0;
+ BiomeGenOriginal *bg = (BiomeGenOriginal *)mg->biomegen;
+
lua_newtable(L);
for (size_t i = 0; i != maplen; i++) {
- lua_pushnumber(L, mg->humidmap[i]);
+ lua_pushnumber(L, bg->humidmap[i]);
lua_rawseti(L, -2, i + 1);
}
@@ -594,24 +600,37 @@ int ModApiMapgen::l_get_mapgen_params(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- MapgenParams *params = &getServer(L)->getEmergeManager()->params;
+ log_deprecated(L, "get_mapgen_params is deprecated; "
+ "use get_mapgen_setting instead");
+
+ std::string value;
+
+ MapSettingsManager *settingsmgr =
+ getServer(L)->getEmergeManager()->map_settings_mgr;
lua_newtable(L);
- lua_pushstring(L, params->mg_name.c_str());
+ settingsmgr->getMapSetting("mg_name", &value);
+ lua_pushstring(L, value.c_str());
lua_setfield(L, -2, "mgname");
- lua_pushinteger(L, params->seed);
+ settingsmgr->getMapSetting("seed", &value);
+ std::istringstream ss(value);
+ u64 seed;
+ ss >> seed;
+ lua_pushinteger(L, seed);
lua_setfield(L, -2, "seed");
- lua_pushinteger(L, params->water_level);
+ settingsmgr->getMapSetting("water_level", &value);
+ lua_pushinteger(L, stoi(value, -32768, 32767));
lua_setfield(L, -2, "water_level");
- lua_pushinteger(L, params->chunksize);
+ settingsmgr->getMapSetting("chunksize", &value);
+ lua_pushinteger(L, stoi(value, -32768, 32767));
lua_setfield(L, -2, "chunksize");
- std::string flagstr = writeFlagString(params->flags, flagdesc_mapgen, U32_MAX);
- lua_pushstring(L, flagstr.c_str());
+ settingsmgr->getMapSetting("mg_flags", &value);
+ lua_pushstring(L, value.c_str());
lua_setfield(L, -2, "flags");
return 1;
@@ -624,44 +643,120 @@ int ModApiMapgen::l_set_mapgen_params(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
+ log_deprecated(L, "set_mapgen_params is deprecated; "
+ "use set_mapgen_setting instead");
+
if (!lua_istable(L, 1))
return 0;
- EmergeManager *emerge = getServer(L)->getEmergeManager();
- if (emerge->isRunning())
- throw LuaError("Cannot set parameters while mapgen is running");
-
- MapgenParams *params = &emerge->params;
- u32 flags = 0, flagmask = 0;
+ MapSettingsManager *settingsmgr =
+ getServer(L)->getEmergeManager()->map_settings_mgr;
lua_getfield(L, 1, "mgname");
- if (lua_isstring(L, -1)) {
- params->mg_name = lua_tostring(L, -1);
- delete params->sparams;
- params->sparams = NULL;
- }
+ if (lua_isstring(L, -1))
+ settingsmgr->setMapSetting("mg_name", lua_tostring(L, -1), true);
lua_getfield(L, 1, "seed");
if (lua_isnumber(L, -1))
- params->seed = lua_tointeger(L, -1);
+ settingsmgr->setMapSetting("seed", lua_tostring(L, -1), true);
lua_getfield(L, 1, "water_level");
if (lua_isnumber(L, -1))
- params->water_level = lua_tointeger(L, -1);
+ settingsmgr->setMapSetting("water_level", lua_tostring(L, -1), true);
lua_getfield(L, 1, "chunksize");
if (lua_isnumber(L, -1))
- params->chunksize = lua_tointeger(L, -1);
+ settingsmgr->setMapSetting("chunksize", lua_tostring(L, -1), true);
warn_if_field_exists(L, 1, "flagmask",
"Deprecated: flags field now includes unset flags.");
- lua_getfield(L, 1, "flagmask");
+
+ lua_getfield(L, 1, "flags");
if (lua_isstring(L, -1))
- params->flags &= ~readFlagString(lua_tostring(L, -1), flagdesc_mapgen, NULL);
+ settingsmgr->setMapSetting("mg_flags", lua_tostring(L, -1), true);
+
+ return 0;
+}
+
+// get_mapgen_setting(name)
+int ModApiMapgen::l_get_mapgen_setting(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ std::string value;
+ MapSettingsManager *settingsmgr =
+ getServer(L)->getEmergeManager()->map_settings_mgr;
- if (getflagsfield(L, 1, "flags", flagdesc_mapgen, &flags, &flagmask)) {
- params->flags &= ~flagmask;
- params->flags |= flags;
+ const char *name = luaL_checkstring(L, 1);
+ if (!settingsmgr->getMapSetting(name, &value))
+ return 0;
+
+ lua_pushstring(L, value.c_str());
+ return 1;
+}
+
+// get_mapgen_setting_noiseparams(name)
+int ModApiMapgen::l_get_mapgen_setting_noiseparams(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ NoiseParams np;
+ MapSettingsManager *settingsmgr =
+ getServer(L)->getEmergeManager()->map_settings_mgr;
+
+ const char *name = luaL_checkstring(L, 1);
+ if (!settingsmgr->getMapSettingNoiseParams(name, &np))
+ return 0;
+
+ push_noiseparams(L, &np);
+ return 1;
+}
+
+// set_mapgen_setting(name, value, override_meta)
+// set mapgen config values
+int ModApiMapgen::l_set_mapgen_setting(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ MapSettingsManager *settingsmgr =
+ getServer(L)->getEmergeManager()->map_settings_mgr;
+
+ 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;
+
+ if (!settingsmgr->setMapSetting(name, value, override_meta)) {
+ errorstream << "set_mapgen_setting: cannot set '"
+ << name << "' after initialization" << std::endl;
+ }
+
+ return 0;
+}
+
+
+// set_mapgen_setting_noiseparams(name, noiseparams, set_default)
+// set mapgen config values for noise parameters
+int ModApiMapgen::l_set_mapgen_setting_noiseparams(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ MapSettingsManager *settingsmgr =
+ getServer(L)->getEmergeManager()->map_settings_mgr;
+
+ const char *name = luaL_checkstring(L, 1);
+
+ NoiseParams np;
+ if (!read_noiseparams(L, 2, &np)) {
+ errorstream << "set_mapgen_setting_noiseparams: cannot set '" << name
+ << "'; invalid noiseparams table" << std::endl;
+ return 0;
+ }
+
+ bool override_meta = lua_isboolean(L, 3) ? lua_toboolean(L, 3) : false;
+
+ if (!settingsmgr->setMapSettingNoiseParams(name, &np, override_meta)) {
+ errorstream << "set_mapgen_setting_noiseparams: cannot set '"
+ << name << "' after initialization" << std::endl;
}
return 0;
@@ -677,8 +772,11 @@ int ModApiMapgen::l_set_noiseparams(lua_State *L)
const char *name = luaL_checkstring(L, 1);
NoiseParams np;
- if (!read_noiseparams(L, 2, &np))
+ if (!read_noiseparams(L, 2, &np)) {
+ errorstream << "set_noiseparams: cannot set '" << name
+ << "'; invalid noiseparams table" << std::endl;
return 0;
+ }
bool set_default = lua_isboolean(L, 3) ? lua_toboolean(L, 3) : true;
@@ -804,6 +902,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
deco->y_min = getintfield_default(L, index, "y_min", -31000);
deco->y_max = getintfield_default(L, index, "y_max", 31000);
+ deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1);
deco->sidelen = getintfield_default(L, index, "sidelen", 8);
if (deco->sidelen <= 0) {
errorstream << "register_decoration: sidelen must be "
@@ -831,6 +930,14 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
errorstream << "register_decoration: couldn't get all biomes " << std::endl;
lua_pop(L, 1);
+ //// Get node name(s) to 'spawn by'
+ size_t nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames);
+ deco->m_nnlistsizes.push_back(nnames);
+ if (nnames == 0 && deco->nspawnby != -1) {
+ errorstream << "register_decoration: no spawn_by nodes defined,"
+ " but num_spawn_by specified" << std::endl;
+ }
+
//// Handle decoration type-specific parameters
bool success = false;
switch (decotype) {
@@ -864,12 +971,11 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
bool read_deco_simple(lua_State *L, DecoSimple *deco)
{
- size_t nnames;
int index = 1;
+ int param2;
deco->deco_height = getintfield_default(L, index, "height", 1);
deco->deco_height_max = getintfield_default(L, index, "height_max", 0);
- deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1);
if (deco->deco_height <= 0) {
errorstream << "register_decoration: simple decoration height"
@@ -877,7 +983,7 @@ bool read_deco_simple(lua_State *L, DecoSimple *deco)
return false;
}
- nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames);
+ size_t nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames);
deco->m_nnlistsizes.push_back(nnames);
if (nnames == 0) {
errorstream << "register_decoration: no decoration nodes "
@@ -885,13 +991,13 @@ bool read_deco_simple(lua_State *L, DecoSimple *deco)
return false;
}
- nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames);
- deco->m_nnlistsizes.push_back(nnames);
- if (nnames == 0 && deco->nspawnby != -1) {
- errorstream << "register_decoration: no spawn_by nodes defined,"
- " but num_spawn_by specified" << std::endl;
+ param2 = getintfield_default(L, index, "param2", 0);
+ if ((param2 < 0) || (param2 > 255)) {
+ errorstream << "register_decoration: param2 out of bounds (0-255)"
+ << std::endl;
return false;
}
+ deco->deco_param2 = (u8)param2;
return true;
}
@@ -1137,7 +1243,7 @@ int ModApiMapgen::l_generate_ores(lua_State *L)
EmergeManager *emerge = getServer(L)->getEmergeManager();
Mapgen mg;
- mg.seed = emerge->params.seed;
+ mg.seed = emerge->mgparams->seed;
mg.vm = LuaVoxelManip::checkobject(L, 1)->vm;
mg.ndef = getServer(L)->getNodeDefManager();
@@ -1163,7 +1269,7 @@ int ModApiMapgen::l_generate_decorations(lua_State *L)
EmergeManager *emerge = getServer(L)->getEmergeManager();
Mapgen mg;
- mg.seed = emerge->params.seed;
+ mg.seed = emerge->mgparams->seed;
mg.vm = LuaVoxelManip::checkobject(L, 1)->vm;
mg.ndef = getServer(L)->getNodeDefManager();
@@ -1189,7 +1295,7 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
const char *filename = luaL_checkstring(L, 4);
- CHECK_SECURE_PATH_OPTIONAL(L, filename);
+ CHECK_SECURE_PATH(L, filename, true);
Map *map = &(getEnv(L)->getMap());
Schematic schem;
@@ -1387,6 +1493,10 @@ void ModApiMapgen::Initialize(lua_State *L, int top)
API_FCT(get_mapgen_params);
API_FCT(set_mapgen_params);
+ API_FCT(get_mapgen_setting);
+ API_FCT(set_mapgen_setting);
+ API_FCT(get_mapgen_setting_noiseparams);
+ API_FCT(set_mapgen_setting_noiseparams);
API_FCT(set_noiseparams);
API_FCT(get_noiseparams);
API_FCT(set_gen_notify);
diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h
index 9751c0db6..bb94575c7 100644
--- a/src/script/lua_api/l_mapgen.h
+++ b/src/script/lua_api/l_mapgen.h
@@ -40,6 +40,18 @@ private:
// set mapgen parameters
static int l_set_mapgen_params(lua_State *L);
+ // get_mapgen_setting(name)
+ static int l_get_mapgen_setting(lua_State *L);
+
+ // set_mapgen_setting(name, value, override_meta)
+ static int l_set_mapgen_setting(lua_State *L);
+
+ // get_mapgen_setting_noiseparams(name)
+ static int l_get_mapgen_setting_noiseparams(lua_State *L);
+
+ // set_mapgen_setting_noiseparams(name, value, override_meta)
+ static int l_set_mapgen_setting_noiseparams(lua_State *L);
+
// set_noiseparam_defaults(name, noiseparams, set_default)
static int l_set_noiseparams(lua_State *L);
diff --git a/src/script/lua_api/l_nodetimer.cpp b/src/script/lua_api/l_nodetimer.cpp
index 601113516..3242d6ea5 100644
--- a/src/script/lua_api/l_nodetimer.cpp
+++ b/src/script/lua_api/l_nodetimer.cpp
@@ -45,7 +45,7 @@ int NodeTimerRef::l_set(lua_State *L)
if(env == NULL) return 0;
f32 t = luaL_checknumber(L,2);
f32 e = luaL_checknumber(L,3);
- env->getMap().setNodeTimer(o->m_p,NodeTimer(t,e));
+ env->getMap().setNodeTimer(NodeTimer(t, e, o->m_p));
return 0;
}
@@ -56,7 +56,7 @@ int NodeTimerRef::l_start(lua_State *L)
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
f32 t = luaL_checknumber(L,2);
- env->getMap().setNodeTimer(o->m_p,NodeTimer(t,0));
+ env->getMap().setNodeTimer(NodeTimer(t, 0, o->m_p));
return 0;
}
diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp
index 04dc6048f..e0039371f 100644
--- a/src/script/lua_api/l_noise.cpp
+++ b/src/script/lua_api/l_noise.cpp
@@ -146,7 +146,7 @@ const luaL_reg LuaPerlinNoise::methods[] = {
LuaPerlinNoiseMap
*/
-LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, int seed, v3s16 size)
+LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, s32 seed, v3s16 size)
{
m_is3d = size.Z > 1;
np = *params;
diff --git a/src/script/lua_api/l_noise.h b/src/script/lua_api/l_noise.h
index 492eb7550..40bfd1315 100644
--- a/src/script/lua_api/l_noise.h
+++ b/src/script/lua_api/l_noise.h
@@ -79,7 +79,7 @@ class LuaPerlinNoiseMap : public ModApiBase {
static int l_getMapSlice(lua_State *L);
public:
- LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size);
+ LuaPerlinNoiseMap(NoiseParams *np, s32 seed, v3s16 size);
~LuaPerlinNoiseMap();
@@ -111,7 +111,7 @@ private:
static int l_next(lua_State *L);
public:
- LuaPseudoRandom(int seed) :
+ LuaPseudoRandom(s32 seed) :
m_pseudo(seed) {}
// LuaPseudoRandom(seed)
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index 6d6614e7d..2a8b8a64e 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -107,7 +107,7 @@ PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
return (PlayerSAO*)obj;
}
-Player* ObjectRef::getplayer(ObjectRef *ref)
+RemotePlayer *ObjectRef::getplayer(ObjectRef *ref)
{
PlayerSAO *playersao = getplayersao(ref);
if (playersao == NULL)
@@ -137,11 +137,12 @@ int ObjectRef::l_remove(lua_State *L)
if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
return 0;
- std::set<int> child_ids = co->getAttachmentChildIds();
- std::set<int>::iterator it;
+ UNORDERED_SET<int> child_ids = co->getAttachmentChildIds();
+ UNORDERED_SET<int>::iterator it;
for (it = child_ids.begin(); it != child_ids.end(); ++it) {
- ServerActiveObject *child = env->getActiveObject(*it);
- child->setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0));
+ // Child can be NULL if it was deleted earlier
+ if (ServerActiveObject *child = env->getActiveObject(*it))
+ child->setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0));
}
verbosestream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
@@ -508,7 +509,7 @@ int ObjectRef::l_set_local_animation(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
// Do it
@@ -533,7 +534,7 @@ int ObjectRef::l_get_local_animation(lua_State *L)
{
NO_MAP_LOCK_REQUIRED
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -554,7 +555,7 @@ int ObjectRef::l_set_eye_offset(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
// Do it
@@ -584,7 +585,7 @@ int ObjectRef::l_get_eye_offset(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
// Do it
@@ -606,10 +607,10 @@ int ObjectRef::l_set_bone_position(lua_State *L)
bone = lua_tostring(L, 2);
v3f position = v3f(0, 0, 0);
if (!lua_isnil(L, 3))
- position = read_v3f(L, 3);
+ position = check_v3f(L, 3);
v3f rotation = v3f(0, 0, 0);
if (!lua_isnil(L, 4))
- rotation = read_v3f(L, 4);
+ rotation = check_v3f(L, 4);
co->setBonePosition(bone, position, rotation);
return 0;
}
@@ -762,7 +763,7 @@ int ObjectRef::l_is_player(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
lua_pushboolean(L, (player != NULL));
return 1;
}
@@ -973,7 +974,7 @@ int ObjectRef::l_is_player_connected(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
lua_pushboolean(L, (player != NULL && player->peer_id != 0));
return 1;
}
@@ -983,7 +984,7 @@ int ObjectRef::l_get_player_name(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL) {
lua_pushlstring(L, "", 0);
return 1;
@@ -998,7 +999,7 @@ int ObjectRef::l_get_player_velocity(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL) {
lua_pushnil(L);
return 1;
@@ -1013,63 +1014,133 @@ int ObjectRef::l_get_look_dir(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
- if (player == NULL) return 0;
+ PlayerSAO* co = getplayersao(ref);
+ if (co == NULL) return 0;
// Do it
- float pitch = player->getRadPitch();
- float yaw = player->getRadYaw();
+ float pitch = co->getRadPitchDep();
+ float yaw = co->getRadYawDep();
v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw));
push_v3f(L, v);
return 1;
}
+// DEPRECATED
// get_look_pitch(self)
int ObjectRef::l_get_look_pitch(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
+
+ log_deprecated(L,
+ "Deprecated call to get_look_pitch, use get_look_vertical instead");
+
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
- if (player == NULL) return 0;
+ PlayerSAO* co = getplayersao(ref);
+ if (co == NULL) return 0;
// Do it
- lua_pushnumber(L, player->getRadPitch());
+ lua_pushnumber(L, co->getRadPitchDep());
return 1;
}
+// DEPRECATED
// get_look_yaw(self)
int ObjectRef::l_get_look_yaw(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
+
+ log_deprecated(L,
+ "Deprecated call to get_look_yaw, use get_look_horizontal instead");
+
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
- if (player == NULL) return 0;
+ PlayerSAO* co = getplayersao(ref);
+ if (co == NULL) return 0;
+ // Do it
+ lua_pushnumber(L, co->getRadYawDep());
+ return 1;
+}
+
+// get_look_pitch2(self)
+int ObjectRef::l_get_look_vertical(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ PlayerSAO* co = getplayersao(ref);
+ if (co == NULL) return 0;
+ // Do it
+ lua_pushnumber(L, co->getRadPitch());
+ return 1;
+}
+
+// get_look_yaw2(self)
+int ObjectRef::l_get_look_horizontal(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ PlayerSAO* co = getplayersao(ref);
+ if (co == NULL) return 0;
+ // Do it
+ lua_pushnumber(L, co->getRadYaw());
+ return 1;
+}
+
+// set_look_vertical(self, radians)
+int ObjectRef::l_set_look_vertical(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ PlayerSAO* co = getplayersao(ref);
+ if (co == NULL) return 0;
+ float pitch = luaL_checknumber(L, 2) * core::RADTODEG;
// Do it
- lua_pushnumber(L, player->getRadYaw());
+ co->setPitchAndSend(pitch);
return 1;
}
+// set_look_horizontal(self, radians)
+int ObjectRef::l_set_look_horizontal(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ PlayerSAO* co = getplayersao(ref);
+ if (co == NULL) return 0;
+ float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
+ // Do it
+ co->setYawAndSend(yaw);
+ return 1;
+}
+
+// DEPRECATED
// set_look_pitch(self, radians)
int ObjectRef::l_set_look_pitch(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
+
+ log_deprecated(L,
+ "Deprecated call to set_look_pitch, use set_look_vertical instead.");
+
ObjectRef *ref = checkobject(L, 1);
PlayerSAO* co = getplayersao(ref);
if (co == NULL) return 0;
float pitch = luaL_checknumber(L, 2) * core::RADTODEG;
// Do it
- co->setPitch(pitch);
+ co->setPitchAndSend(pitch);
return 1;
}
+// DEPRECATED
// set_look_yaw(self, radians)
int ObjectRef::l_set_look_yaw(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
+
+ log_deprecated(L,
+ "Deprecated call to set_look_yaw, use set_look_horizontal instead.");
+
ObjectRef *ref = checkobject(L, 1);
PlayerSAO* co = getplayersao(ref);
if (co == NULL) return 0;
float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
// Do it
- co->setYaw(yaw);
+ co->setYawAndSend(yaw);
return 1;
}
@@ -1109,7 +1180,7 @@ int ObjectRef::l_set_inventory_formspec(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL) return 0;
std::string formspec = luaL_checkstring(L, 2);
@@ -1124,7 +1195,7 @@ int ObjectRef::l_get_inventory_formspec(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL) return 0;
std::string formspec = player->inventory_formspec;
@@ -1137,13 +1208,13 @@ int ObjectRef::l_get_player_control(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL) {
lua_pushlstring(L, "", 0);
return 1;
}
- // Do it
- PlayerControl control = player->getPlayerControl();
+
+ const PlayerControl &control = player->getPlayerControl();
lua_newtable(L);
lua_pushboolean(L, control.up);
lua_setfield(L, -2, "up");
@@ -1171,7 +1242,7 @@ int ObjectRef::l_get_player_control_bits(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL) {
lua_pushlstring(L, "", 0);
return 1;
@@ -1186,7 +1257,7 @@ int ObjectRef::l_hud_add(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1249,7 +1320,7 @@ int ObjectRef::l_hud_remove(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1269,7 +1340,7 @@ int ObjectRef::l_hud_change(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1346,7 +1417,7 @@ int ObjectRef::l_hud_get(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1397,7 +1468,7 @@ int ObjectRef::l_hud_set_flags(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1423,7 +1494,7 @@ int ObjectRef::l_hud_get_flags(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1449,7 +1520,7 @@ int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1467,7 +1538,7 @@ int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1482,7 +1553,7 @@ int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1497,7 +1568,7 @@ int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1511,7 +1582,7 @@ int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1526,11 +1597,11 @@ int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
- std::string name = getServer(L)->hudGetHotbarSelectedImage(player);
+ const std::string &name = getServer(L)->hudGetHotbarSelectedImage(player);
lua_pushlstring(L, name.c_str(), name.size());
return 1;
}
@@ -1540,7 +1611,7 @@ int ObjectRef::l_set_sky(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1579,7 +1650,7 @@ int ObjectRef::l_get_sky(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
video::SColor bgcolor(255, 255, 255, 255);
@@ -1607,7 +1678,7 @@ int ObjectRef::l_override_day_night_ratio(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1630,7 +1701,7 @@ int ObjectRef::l_get_day_night_ratio(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
+ RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@@ -1754,6 +1825,10 @@ const luaL_reg ObjectRef::methods[] = {
luamethod(ObjectRef, get_look_dir),
luamethod(ObjectRef, get_look_pitch),
luamethod(ObjectRef, get_look_yaw),
+ luamethod(ObjectRef, get_look_vertical),
+ luamethod(ObjectRef, get_look_horizontal),
+ luamethod(ObjectRef, set_look_horizontal),
+ luamethod(ObjectRef, set_look_vertical),
luamethod(ObjectRef, set_look_yaw),
luamethod(ObjectRef, set_look_pitch),
luamethod(ObjectRef, get_breath),
diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h
index a4457cc05..09f10e417 100644
--- a/src/script/lua_api/l_object.h
+++ b/src/script/lua_api/l_object.h
@@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class ServerActiveObject;
class LuaEntitySAO;
class PlayerSAO;
-class Player;
+class RemotePlayer;
/*
ObjectRef
@@ -47,7 +47,7 @@ private:
static PlayerSAO* getplayersao(ObjectRef *ref);
- static Player* getplayer(ObjectRef *ref);
+ static RemotePlayer *getplayer(ObjectRef *ref);
// Exported functions
@@ -189,15 +189,31 @@ private:
// get_look_dir(self)
static int l_get_look_dir(lua_State *L);
+ // DEPRECATED
// get_look_pitch(self)
static int l_get_look_pitch(lua_State *L);
+ // DEPRECATED
// get_look_yaw(self)
static int l_get_look_yaw(lua_State *L);
+ // get_look_pitch2(self)
+ static int l_get_look_vertical(lua_State *L);
+
+ // get_look_yaw2(self)
+ static int l_get_look_horizontal(lua_State *L);
+
+ // set_look_vertical(self, radians)
+ static int l_set_look_vertical(lua_State *L);
+
+ // set_look_horizontal(self, radians)
+ static int l_set_look_horizontal(lua_State *L);
+
+ // DEPRECATED
// set_look_pitch(self, radians)
static int l_set_look_pitch(lua_State *L);
+ // DEPRECATED
// set_look_yaw(self, radians)
static int l_set_look_yaw(lua_State *L);
diff --git a/src/script/lua_api/l_particles.cpp b/src/script/lua_api/l_particles.cpp
index f6c1725de..667ac7272 100644
--- a/src/script/lua_api/l_particles.cpp
+++ b/src/script/lua_api/l_particles.cpp
@@ -18,16 +18,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "lua_api/l_particles.h"
+#include "lua_api/l_object.h"
#include "lua_api/l_internal.h"
#include "common/c_converter.h"
#include "server.h"
+#include "particles.h"
// add_particle({pos=, velocity=, acceleration=, expirationtime=,
-// size=, collisiondetection=, vertical=, texture=, player=})
+// size=, collisiondetection=, collision_removal=, vertical=,
+// texture=, player=})
// pos/velocity/acceleration = {x=num, y=num, z=num}
// expirationtime = num (seconds)
// size = num
// collisiondetection = bool
+// collision_removal = bool
// vertical = bool
// texture = e.g."default_wood.png"
int ModApiParticles::l_add_particle(lua_State *L)
@@ -41,8 +45,8 @@ int ModApiParticles::l_add_particle(lua_State *L)
float expirationtime, size;
expirationtime = size = 1;
- bool collisiondetection, vertical;
- collisiondetection = vertical = false;
+ bool collisiondetection, vertical, collision_removal;
+ collisiondetection = vertical = collision_removal = false;
std::string texture = "";
std::string playername = "";
@@ -94,12 +98,14 @@ int ModApiParticles::l_add_particle(lua_State *L)
size = getfloatfield_default(L, 1, "size", 1);
collisiondetection = getboolfield_default(L, 1,
"collisiondetection", collisiondetection);
+ collision_removal = getboolfield_default(L, 1,
+ "collision_removal", collision_removal);
vertical = getboolfield_default(L, 1, "vertical", vertical);
texture = getstringfield_default(L, 1, "texture", "");
playername = getstringfield_default(L, 1, "playername", "");
}
- getServer(L)->spawnParticle(playername, pos, vel, acc,
- expirationtime, size, collisiondetection, vertical, texture);
+ getServer(L)->spawnParticle(playername, pos, vel, acc, expirationtime, size,
+ collisiondetection, collision_removal, vertical, texture);
return 1;
}
@@ -110,6 +116,7 @@ int ModApiParticles::l_add_particle(lua_State *L)
// minexptime=, maxexptime=,
// minsize=, maxsize=,
// collisiondetection=,
+// collision_removal=,
// vertical=,
// texture=,
// player=})
@@ -117,6 +124,7 @@ int ModApiParticles::l_add_particle(lua_State *L)
// minexptime/maxexptime = num (seconds)
// minsize/maxsize = num
// collisiondetection = bool
+// collision_removal = bool
// vertical = bool
// texture = e.g."default_wood.png"
int ModApiParticles::l_add_particlespawner(lua_State *L)
@@ -129,8 +137,9 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
minpos= maxpos= minvel= maxvel= minacc= maxacc= v3f(0, 0, 0);
float time, minexptime, maxexptime, minsize, maxsize;
time= minexptime= maxexptime= minsize= maxsize= 1;
- bool collisiondetection, vertical;
- collisiondetection= vertical= false;
+ bool collisiondetection, vertical, collision_removal;
+ collisiondetection = vertical = collision_removal = false;
+ ServerActiveObject *attached = NULL;
std::string texture = "";
std::string playername = "";
@@ -189,6 +198,16 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
maxsize = getfloatfield_default(L, 1, "maxsize", maxsize);
collisiondetection = getboolfield_default(L, 1,
"collisiondetection", collisiondetection);
+ collision_removal = getboolfield_default(L, 1,
+ "collision_removal", collision_removal);
+
+ lua_getfield(L, 1, "attached");
+ if (!lua_isnil(L, -1)) {
+ ObjectRef *ref = ObjectRef::checkobject(L, -1);
+ lua_pop(L, 1);
+ attached = ObjectRef::getobject(ref);
+ }
+
vertical = getboolfield_default(L, 1, "vertical", vertical);
texture = getstringfield_default(L, 1, "texture", "");
playername = getstringfield_default(L, 1, "playername", "");
@@ -201,6 +220,8 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
minexptime, maxexptime,
minsize, maxsize,
collisiondetection,
+ collision_removal,
+ attached,
vertical,
texture, playername);
lua_pushnumber(L, id);
diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp
index 59d3f5c70..b6d44e0ff 100644
--- a/src/script/lua_api/l_server.cpp
+++ b/src/script/lua_api/l_server.cpp
@@ -45,6 +45,15 @@ int ModApiServer::l_get_server_status(lua_State *L)
return 1;
}
+// get_server_uptime()
+int ModApiServer::l_get_server_uptime(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ lua_pushnumber(L, getServer(L)->getUptime());
+ return 1;
+}
+
+
// print(text)
int ModApiServer::l_print(lua_State *L)
{
@@ -106,7 +115,7 @@ int ModApiServer::l_get_player_ip(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
const char * name = luaL_checkstring(L, 1);
- Player *player = getEnv(L)->getPlayer(name);
+ RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
if(player == NULL)
{
lua_pushnil(L); // no such player
@@ -133,9 +142,8 @@ int ModApiServer::l_get_player_information(lua_State *L)
NO_MAP_LOCK_REQUIRED;
const char * name = luaL_checkstring(L, 1);
- Player *player = getEnv(L)->getPlayer(name);
- if(player == NULL)
- {
+ RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
+ if (player == NULL) {
lua_pushnil(L); // no such player
return 1;
}
@@ -278,15 +286,15 @@ int ModApiServer::l_ban_player(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
const char * name = luaL_checkstring(L, 1);
- Player *player = getEnv(L)->getPlayer(name);
- if(player == NULL)
- {
+ RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
+ if (player == NULL) {
lua_pushboolean(L, false); // no such player
return 1;
}
try
{
- Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id);
+ Address addr = getServer(L)->getPeerAddress(
+ dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name)->peer_id);
std::string ip_str = addr.serializeString();
getServer(L)->setIpBanned(ip_str, name);
}
@@ -314,9 +322,9 @@ int ModApiServer::l_kick_player(lua_State *L)
{
message = "Kicked.";
}
- Player *player = getEnv(L)->getPlayer(name);
- if (player == NULL)
- {
+
+ RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
+ if (player == NULL) {
lua_pushboolean(L, false); // No such player
return 1;
}
@@ -508,6 +516,7 @@ void ModApiServer::Initialize(lua_State *L, int top)
{
API_FCT(request_shutdown);
API_FCT(get_server_status);
+ API_FCT(get_server_uptime);
API_FCT(get_worldpath);
API_FCT(is_singleplayer);
diff --git a/src/script/lua_api/l_server.h b/src/script/lua_api/l_server.h
index 06a5ddc24..1ad46d440 100644
--- a/src/script/lua_api/l_server.h
+++ b/src/script/lua_api/l_server.h
@@ -30,6 +30,9 @@ private:
// get_server_status()
static int l_get_server_status(lua_State *L);
+ // get_server_uptime()
+ static int l_get_server_uptime(lua_State *L);
+
// get_worldpath()
static int l_get_worldpath(lua_State *L);
diff --git a/src/script/lua_api/l_settings.cpp b/src/script/lua_api/l_settings.cpp
index 35b82b435..d3fe03005 100644
--- a/src/script/lua_api/l_settings.cpp
+++ b/src/script/lua_api/l_settings.cpp
@@ -118,6 +118,11 @@ int LuaSettings::l_write(lua_State* L)
NO_MAP_LOCK_REQUIRED;
LuaSettings* o = checkobject(L, 1);
+ if (!o->m_write_allowed) {
+ throw LuaError("Settings: writing " + o->m_filename +
+ " not allowed with mod security on.");
+ }
+
bool success = o->m_settings->updateConfigFile(o->m_filename.c_str());
lua_pushboolean(L, success);
@@ -142,8 +147,9 @@ int LuaSettings::l_to_table(lua_State* L)
return 1;
}
-LuaSettings::LuaSettings(const char* filename)
+LuaSettings::LuaSettings(const char* filename, bool write_allowed)
{
+ m_write_allowed = write_allowed;
m_filename = std::string(filename);
m_settings = new Settings();
@@ -188,9 +194,10 @@ void LuaSettings::Register(lua_State* L)
int LuaSettings::create_object(lua_State* L)
{
NO_MAP_LOCK_REQUIRED;
+ bool write_allowed = true;
const char* filename = luaL_checkstring(L, 1);
- CHECK_SECURE_PATH_OPTIONAL(L, filename);
- LuaSettings* o = new LuaSettings(filename);
+ CHECK_SECURE_PATH_POSSIBLE_WRITE(L, filename, &write_allowed);
+ LuaSettings* o = new LuaSettings(filename, write_allowed);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
diff --git a/src/script/lua_api/l_settings.h b/src/script/lua_api/l_settings.h
index cb0c09a73..bca333e31 100644
--- a/src/script/lua_api/l_settings.h
+++ b/src/script/lua_api/l_settings.h
@@ -53,11 +53,12 @@ private:
// to_table(self) -> {[key1]=value1,...}
static int l_to_table(lua_State* L);
+ bool m_write_allowed;
Settings* m_settings;
std::string m_filename;
public:
- LuaSettings(const char* filename);
+ LuaSettings(const char* filename, bool write_allowed);
~LuaSettings();
// LuaSettings(filename)
diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp
index c3e6c8964..26e2b985c 100644
--- a/src/script/lua_api/l_util.cpp
+++ b/src/script/lua_api/l_util.cpp
@@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_content.h"
#include "cpp_api/s_async.h"
#include "serialization.h"
-#include "json/json.h"
+#include <json/json.h>
#include "cpp_api/s_security.h"
#include "porting.h"
#include "debug.h"
@@ -32,8 +32,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "filesys.h"
#include "settings.h"
#include "util/auth.h"
+#include "util/base64.h"
+#include "config.h"
+#include "version.h"
#include <algorithm>
+
// log([level,] text)
// Writes a line to the logger.
// The one-argument version logs to infostream.
@@ -219,7 +223,7 @@ int ModApiUtil::l_write_json(lua_State *L)
int ModApiUtil::l_get_dig_params(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- std::map<std::string, int> groups;
+ ItemGroupList groups;
read_groups(L, 1, groups);
ToolCapabilities tp = read_tool_capabilities(L, 2);
if(lua_isnoneornil(L, 3))
@@ -234,7 +238,7 @@ int ModApiUtil::l_get_dig_params(lua_State *L)
int ModApiUtil::l_get_hit_params(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- std::map<std::string, int> groups;
+ UNORDERED_MAP<std::string, int> groups;
read_groups(L, 1, groups);
ToolCapabilities tp = read_tool_capabilities(L, 2);
if(lua_isnoneornil(L, 3))
@@ -245,6 +249,35 @@ int ModApiUtil::l_get_hit_params(lua_State *L)
return 1;
}
+// check_password_entry(name, entry, password)
+int ModApiUtil::l_check_password_entry(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ std::string name = luaL_checkstring(L, 1);
+ std::string entry = luaL_checkstring(L, 2);
+ std::string password = luaL_checkstring(L, 3);
+
+ if (base64_is_valid(entry)) {
+ std::string hash = translate_password(name, password);
+ lua_pushboolean(L, hash == entry);
+ return 1;
+ }
+
+ std::string salt;
+ std::string verifier;
+
+ if (!decode_srp_verifier_and_salt(entry, &verifier, &salt)) {
+ // invalid format
+ warningstream << "Invalid password format for " << name << std::endl;
+ lua_pushboolean(L, false);
+ return 1;
+ }
+ std::string gen_verifier = generate_srp_verifier(name, password, salt);
+
+ lua_pushboolean(L, gen_verifier == verifier);
+ return 1;
+}
+
// get_password_hash(name, raw_password)
int ModApiUtil::l_get_password_hash(lua_State *L)
{
@@ -272,12 +305,14 @@ int ModApiUtil::l_is_yes(lua_State *L)
return 1;
}
+// get_builtin_path()
int ModApiUtil::l_get_builtin_path(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
std::string path = porting::path_share + DIR_DELIM + "builtin";
lua_pushstring(L, path.c_str());
+
return 1;
}
@@ -320,12 +355,40 @@ int ModApiUtil::l_decompress(lua_State *L)
return 1;
}
+// encode_base64(string)
+int ModApiUtil::l_encode_base64(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ size_t size;
+ const char *data = luaL_checklstring(L, 1, &size);
+
+ std::string out = base64_encode((const unsigned char *)(data), size);
+
+ lua_pushlstring(L, out.data(), out.size());
+ return 1;
+}
+
+// decode_base64(string)
+int ModApiUtil::l_decode_base64(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ size_t size;
+ const char *data = luaL_checklstring(L, 1, &size);
+
+ std::string out = base64_decode(std::string(data, size));
+
+ lua_pushlstring(L, out.data(), out.size());
+ return 1;
+}
+
// mkdir(path)
int ModApiUtil::l_mkdir(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
const char *path = luaL_checkstring(L, 1);
- CHECK_SECURE_PATH_OPTIONAL(L, path);
+ CHECK_SECURE_PATH(L, path, true);
lua_pushboolean(L, fs::CreateAllDirs(path));
return 1;
}
@@ -337,7 +400,7 @@ int ModApiUtil::l_get_dir_list(lua_State *L)
const char *path = luaL_checkstring(L, 1);
short is_dir = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : -1;
- CHECK_SECURE_PATH_OPTIONAL(L, path);
+ CHECK_SECURE_PATH(L, path, false);
std::vector<fs::DirListNode> list = fs::GetDirListing(path);
@@ -388,8 +451,9 @@ int ModApiUtil::l_request_insecure_environment(lua_State *L)
// Check secure.trusted_mods
const char *mod_name = lua_tostring(L, -1);
std::string trusted_mods = g_settings->get("secure.trusted_mods");
- trusted_mods.erase(std::remove(trusted_mods.begin(),
- trusted_mods.end(), ' '), trusted_mods.end());
+ trusted_mods.erase(std::remove_if(trusted_mods.begin(),
+ trusted_mods.end(), static_cast<int(*)(int)>(&std::isspace)),
+ trusted_mods.end());
std::vector<std::string> mod_list = str_split(trusted_mods, ',');
if (std::find(mod_list.begin(), mod_list.end(), mod_name) ==
mod_list.end()) {
@@ -401,6 +465,26 @@ int ModApiUtil::l_request_insecure_environment(lua_State *L)
return 1;
}
+// get_version()
+int ModApiUtil::l_get_version(lua_State *L)
+{
+ lua_createtable(L, 0, 3);
+ int table = lua_gettop(L);
+
+ lua_pushstring(L, PROJECT_NAME_C);
+ lua_setfield(L, table, "project");
+
+ lua_pushstring(L, g_version_string);
+ lua_setfield(L, table, "string");
+
+ if (strcmp(g_version_string, g_version_hash)) {
+ lua_pushstring(L, g_version_hash);
+ lua_setfield(L, table, "hash");
+ }
+
+ return 1;
+}
+
void ModApiUtil::Initialize(lua_State *L, int top)
{
@@ -420,6 +504,7 @@ void ModApiUtil::Initialize(lua_State *L, int top)
API_FCT(get_dig_params);
API_FCT(get_hit_params);
+ API_FCT(check_password_entry);
API_FCT(get_password_hash);
API_FCT(is_yes);
@@ -433,6 +518,11 @@ void ModApiUtil::Initialize(lua_State *L, int top)
API_FCT(get_dir_list);
API_FCT(request_insecure_environment);
+
+ API_FCT(encode_base64);
+ API_FCT(decode_base64);
+
+ API_FCT(get_version);
}
void ModApiUtil::InitializeAsync(AsyncEngine& engine)
@@ -459,5 +549,10 @@ void ModApiUtil::InitializeAsync(AsyncEngine& engine)
ASYNC_API_FCT(mkdir);
ASYNC_API_FCT(get_dir_list);
+
+ ASYNC_API_FCT(encode_base64);
+ ASYNC_API_FCT(decode_base64);
+
+ ASYNC_API_FCT(get_version);
}
diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h
index 6fac7e7eb..9910704b3 100644
--- a/src/script/lua_api/l_util.h
+++ b/src/script/lua_api/l_util.h
@@ -71,6 +71,9 @@ private:
// get_hit_params(groups, tool_capabilities[, time_from_last_punch])
static int l_get_hit_params(lua_State *L);
+ // check_password_entry(name, entry, password)
+ static int l_check_password_entry(lua_State *L);
+
// get_password_hash(name, raw_password)
static int l_get_password_hash(lua_State *L);
@@ -95,6 +98,15 @@ private:
// request_insecure_environment()
static int l_request_insecure_environment(lua_State *L);
+ // encode_base64(string)
+ static int l_encode_base64(lua_State *L);
+
+ // decode_base64(string)
+ static int l_decode_base64(lua_State *L);
+
+ // get_version()
+ static int l_get_version(lua_State *L);
+
public:
static void Initialize(lua_State *L, int top);
diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp
index f13866408..bdf720f0a 100644
--- a/src/script/lua_api/l_vmanip.cpp
+++ b/src/script/lua_api/l_vmanip.cpp
@@ -190,7 +190,7 @@ int LuaVoxelManip::l_calc_lighting(lua_State *L)
Mapgen mg;
mg.vm = vm;
mg.ndef = ndef;
- mg.water_level = emerge->params.water_level;
+ mg.water_level = emerge->mgparams->water_level;
mg.calcLighting(pmin, pmax, fpmin, fpmax, propagate_shadow);
@@ -277,11 +277,17 @@ int LuaVoxelManip::l_get_param2_data(lua_State *L)
NO_MAP_LOCK_REQUIRED;
LuaVoxelManip *o = checkobject(L, 1);
+ bool use_buffer = lua_istable(L, 2);
+
MMVManip *vm = o->vm;
u32 volume = vm->m_area.getVolume();
- lua_newtable(L);
+ if (use_buffer)
+ lua_pushvalue(L, 2);
+ else
+ lua_newtable(L);
+
for (u32 i = 0; i != volume; i++) {
lua_Integer param2 = vm->m_data[i].param2;
lua_pushinteger(L, param2);