aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
authorElias Fleckenstein <eliasfleckenstein@web.de>2021-09-19 20:56:13 +0200
committerElias Fleckenstein <eliasfleckenstein@web.de>2021-09-19 20:56:13 +0200
commitc8900e169a1ddceec07a449f1ae7c4322ff02036 (patch)
tree5156605fb473d25786426eb6876ba2e7d3b7507b /src/script
parent950d2c9b3e10cbace9236e820c8119d1abb9e01f (diff)
parente0529da5c84f224c380e6d5e063392cb01f85683 (diff)
downloaddragonfireclient-c8900e169a1ddceec07a449f1ae7c4322ff02036.tar.xz
Merge branch 'master' of https://github.com/minetest/minetest
Diffstat (limited to 'src/script')
-rw-r--r--src/script/common/c_content.cpp56
-rw-r--r--src/script/common/c_content.h14
-rw-r--r--src/script/common/c_converter.cpp30
-rw-r--r--src/script/common/c_internal.cpp84
-rw-r--r--src/script/common/c_internal.h16
-rw-r--r--src/script/cpp_api/s_async.cpp108
-rw-r--r--src/script/cpp_api/s_async.h39
-rw-r--r--src/script/cpp_api/s_base.cpp4
-rw-r--r--src/script/cpp_api/s_base.h8
-rw-r--r--src/script/cpp_api/s_client.cpp88
-rw-r--r--src/script/cpp_api/s_env.cpp63
-rw-r--r--src/script/cpp_api/s_env.h5
-rw-r--r--src/script/cpp_api/s_item.cpp15
-rw-r--r--src/script/cpp_api/s_mainmenu.h2
-rw-r--r--src/script/cpp_api/s_nodemeta.cpp18
-rw-r--r--src/script/cpp_api/s_security.cpp21
-rw-r--r--src/script/cpp_api/s_server.cpp66
-rw-r--r--src/script/cpp_api/s_server.h6
-rw-r--r--src/script/lua_api/l_areastore.cpp2
-rw-r--r--src/script/lua_api/l_auth.cpp5
-rw-r--r--src/script/lua_api/l_camera.cpp2
-rw-r--r--src/script/lua_api/l_env.cpp32
-rw-r--r--src/script/lua_api/l_env.h22
-rw-r--r--src/script/lua_api/l_http.cpp8
-rw-r--r--src/script/lua_api/l_inventory.cpp2
-rw-r--r--src/script/lua_api/l_item.cpp2
-rw-r--r--src/script/lua_api/l_itemstackmeta.cpp2
-rw-r--r--src/script/lua_api/l_localplayer.cpp27
-rw-r--r--src/script/lua_api/l_mainmenu.cpp41
-rw-r--r--src/script/lua_api/l_mainmenu.h2
-rw-r--r--src/script/lua_api/l_mapgen.cpp4
-rw-r--r--src/script/lua_api/l_minimap.cpp2
-rw-r--r--src/script/lua_api/l_modchannels.cpp2
-rw-r--r--src/script/lua_api/l_nodemeta.cpp4
-rw-r--r--src/script/lua_api/l_nodetimer.cpp2
-rw-r--r--src/script/lua_api/l_noise.cpp10
-rw-r--r--src/script/lua_api/l_object.cpp38
-rw-r--r--src/script/lua_api/l_playermeta.cpp2
-rw-r--r--src/script/lua_api/l_server.cpp67
-rw-r--r--src/script/lua_api/l_server.h8
-rw-r--r--src/script/lua_api/l_settings.cpp2
-rw-r--r--src/script/lua_api/l_storage.cpp2
-rw-r--r--src/script/lua_api/l_util.cpp85
-rw-r--r--src/script/lua_api/l_util.h12
-rw-r--r--src/script/lua_api/l_vmanip.cpp2
-rw-r--r--src/script/scripting_mainmenu.cpp6
-rw-r--r--src/script/scripting_mainmenu.h5
47 files changed, 646 insertions, 397 deletions
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index 897ca2862..8ca3a722f 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -203,8 +203,6 @@ void read_object_properties(lua_State *L, int index,
if (sao && prop->hp_max < sao->getHP()) {
PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP);
sao->setHP(prop->hp_max, reason);
- if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER)
- sao->getEnv()->getGameDef()->SendPlayerHPOrDie((PlayerSAO *)sao, reason);
}
}
@@ -1407,26 +1405,28 @@ void read_inventory_list(lua_State *L, int tableindex,
{
if(tableindex < 0)
tableindex = lua_gettop(L) + 1 + tableindex;
+
// If nil, delete list
if(lua_isnil(L, tableindex)){
inv->deleteList(name);
return;
}
- // Otherwise set list
+
+ // Get Lua-specified items to insert into the list
std::vector<ItemStack> items = read_items(L, tableindex,srv);
- int listsize = (forcesize != -1) ? forcesize : items.size();
+ size_t listsize = (forcesize >= 0) ? forcesize : items.size();
+
+ // Create or resize/clear list
InventoryList *invlist = inv->addList(name, listsize);
- int index = 0;
- for(std::vector<ItemStack>::const_iterator
- i = items.begin(); i != items.end(); ++i){
- if(forcesize != -1 && index == forcesize)
- break;
- invlist->changeItem(index, *i);
- index++;
+ if (!invlist) {
+ luaL_error(L, "inventory list: cannot create list named '%s'", name);
+ return;
}
- while(forcesize != -1 && index < forcesize){
- invlist->deleteItem(index);
- index++;
+
+ for (size_t i = 0; i < items.size(); ++i) {
+ if (i == listsize)
+ break; // Truncate provided list of items
+ invlist->changeItem(i, items[i]);
}
}
@@ -2013,6 +2013,8 @@ void read_hud_element(lua_State *L, HudElement *elem)
elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f();
lua_pop(L, 1);
+ elem->style = getintfield_default(L, 2, "style", 0);
+
/* check for known deprecated element usage */
if ((elem->type == HUD_ELEM_STATBAR) && (elem->size == v2s32()))
log_deprecated(L,"Deprecated usage of statbar without size!");
@@ -2067,17 +2069,22 @@ void push_hud_element(lua_State *L, HudElement *elem)
lua_pushstring(L, elem->text2.c_str());
lua_setfield(L, -2, "text2");
+
+ lua_pushinteger(L, elem->style);
+ lua_setfield(L, -2, "style");
}
-HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
+bool read_hud_change(lua_State *L, HudElementStat &stat, HudElement *elem, void **value)
{
- HudElementStat stat = HUD_STAT_NUMBER;
- std::string statstr;
- if (lua_isstring(L, 3)) {
+ std::string statstr = lua_tostring(L, 3);
+ {
int statint;
- statstr = lua_tostring(L, 3);
- stat = string_to_enum(es_HudElementStat, statint, statstr) ?
- (HudElementStat)statint : stat;
+ if (!string_to_enum(es_HudElementStat, statint, statstr)) {
+ script_log_unique(L, "Unknown HUD stat type: " + statstr, warningstream);
+ return false;
+ }
+
+ stat = (HudElementStat)statint;
}
switch (stat) {
@@ -2135,8 +2142,13 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
elem->text2 = luaL_checkstring(L, 4);
*value = &elem->text2;
break;
+ case HUD_STAT_STYLE:
+ elem->style = luaL_checknumber(L, 4);
+ *value = &elem->style;
+ break;
}
- return stat;
+
+ return true;
}
/******************************************************************************/
diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h
index dc8f19ef3..1aed7901e 100644
--- a/src/script/common/c_content.h
+++ b/src/script/common/c_content.h
@@ -122,7 +122,7 @@ void push_object_properties (lua_State *L,
void push_inventory (lua_State *L,
Inventory *inventory);
-
+
void push_inventory_list (lua_State *L,
Inventory *inv,
const char *name);
@@ -197,14 +197,14 @@ void read_json_value (lua_State *L, Json::Value &root,
void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm =
false, bool hitpoint = false);
-void push_objectRef (lua_State *L, const u16 id);
+void push_objectRef (lua_State *L, const u16 id);
-void read_hud_element (lua_State *L, HudElement *elem);
+void read_hud_element (lua_State *L, HudElement *elem);
-void push_hud_element (lua_State *L, HudElement *elem);
+void push_hud_element (lua_State *L, HudElement *elem);
-HudElementStat read_hud_change (lua_State *L, HudElement *elem, void **value);
+bool read_hud_change (lua_State *L, HudElementStat &stat, HudElement *elem, void **value);
-void push_collision_move_result(lua_State *L, const collisionMoveResult &res);
+void push_collision_move_result(lua_State *L, const collisionMoveResult &res);
-void push_physics_override (lua_State *L, float speed, float jump, float gravity, bool sneak, bool sneak_glitch, bool new_move);
+void push_physics_override (lua_State *L, float speed, float jump, float gravity, bool sneak, bool sneak_glitch, bool new_move);
diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp
index c00401b58..19734b913 100644
--- a/src/script/common/c_converter.cpp
+++ b/src/script/common/c_converter.cpp
@@ -51,12 +51,32 @@ if (value < F1000_MIN || value > F1000_MAX) { \
#define CHECK_POS_TAB(index) CHECK_TYPE(index, "position", LUA_TTABLE)
+/**
+ * A helper which sets (if available) the vector metatable from builtin as metatable
+ * for the table on top of the stack
+ */
+static void set_vector_metatable(lua_State *L)
+{
+ // get vector.metatable
+ lua_getglobal(L, "vector");
+ if (!lua_istable(L, -1)) {
+ // there is no global vector table
+ lua_pop(L, 1);
+ errorstream << "set_vector_metatable in c_converter.cpp: " <<
+ "missing global vector table" << std::endl;
+ return;
+ }
+ lua_getfield(L, -1, "metatable");
+ // set the metatable
+ lua_setmetatable(L, -3);
+ // pop vector global
+ lua_pop(L, 1);
+}
+
+
void push_float_string(lua_State *L, float value)
{
- std::stringstream ss;
- std::string str;
- ss << value;
- str = ss.str();
+ auto str = ftos(value);
lua_pushstring(L, str.c_str());
}
@@ -69,6 +89,7 @@ void push_v3f(lua_State *L, v3f p)
lua_setfield(L, -2, "y");
lua_pushnumber(L, p.Z);
lua_setfield(L, -2, "z");
+ set_vector_metatable(L);
}
void push_v2f(lua_State *L, v2f p)
@@ -281,6 +302,7 @@ void push_v3s16(lua_State *L, v3s16 p)
lua_setfield(L, -2, "y");
lua_pushinteger(L, p.Z);
lua_setfield(L, -2, "z");
+ set_vector_metatable(L);
}
v3s16 read_v3s16(lua_State *L, int index)
diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp
index ad5f836c5..df82dba14 100644
--- a/src/script/common/c_internal.cpp
+++ b/src/script/common/c_internal.cpp
@@ -18,10 +18,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "common/c_internal.h"
+#include "util/numeric.h"
#include "debug.h"
#include "log.h"
#include "porting.h"
#include "settings.h"
+#include <algorithm> // std::find
std::string script_get_backtrace(lua_State *L)
{
@@ -99,60 +101,35 @@ void script_error(lua_State *L, int pcall_result, const char *mod, const char *f
throw LuaError(err_msg);
}
-// Push the list of callbacks (a lua table).
-// Then push nargs arguments.
-// Then call this function, which
-// - runs the callbacks
-// - replaces the table and arguments with the return value,
-// computed depending on mode
-void script_run_callbacks_f(lua_State *L, int nargs,
- RunCallbacksMode mode, const char *fxn)
-{
- FATAL_ERROR_IF(lua_gettop(L) < nargs + 1, "Not enough arguments");
-
- // Insert error handler
- PUSH_ERROR_HANDLER(L);
- int error_handler = lua_gettop(L) - nargs - 1;
- lua_insert(L, error_handler);
-
- // Insert run_callbacks between error handler and table
- lua_getglobal(L, "core");
- lua_getfield(L, -1, "run_callbacks");
- lua_remove(L, -2);
- lua_insert(L, error_handler + 1);
-
- // Insert mode after table
- lua_pushnumber(L, (int) mode);
- lua_insert(L, error_handler + 3);
-
- // Stack now looks like this:
- // ... <error handler> <run_callbacks> <table> <mode> <arg#1> <arg#2> ... <arg#n>
-
- int result = lua_pcall(L, nargs + 2, 1, error_handler);
- if (result != 0)
- script_error(L, result, NULL, fxn);
-
- lua_remove(L, error_handler);
-}
-
-static void script_log(lua_State *L, const std::string &message,
- std::ostream &log_to, bool do_error, int stack_depth)
+static void script_log_add_source(lua_State *L, std::string &message, int stack_depth)
{
lua_Debug ar;
- log_to << message << " ";
if (lua_getstack(L, stack_depth, &ar)) {
FATAL_ERROR_IF(!lua_getinfo(L, "Sl", &ar), "lua_getinfo() failed");
- log_to << "(at " << ar.short_src << ":" << ar.currentline << ")";
+ message.append(" (at " + std::string(ar.short_src) + ":"
+ + std::to_string(ar.currentline) + ")");
} else {
- log_to << "(at ?:?)";
+ message.append(" (at ?:?)");
}
- log_to << std::endl;
+}
- if (do_error)
- script_error(L, LUA_ERRRUN, NULL, NULL);
- else
- infostream << script_get_backtrace(L) << std::endl;
+bool script_log_unique(lua_State *L, std::string message, std::ostream &log_to,
+ int stack_depth)
+{
+ thread_local std::vector<u64> logged_messages;
+
+ script_log_add_source(L, message, stack_depth);
+ u64 hash = murmur_hash_64_ua(message.data(), message.length(), 0xBADBABE);
+
+ if (std::find(logged_messages.begin(), logged_messages.end(), hash)
+ == logged_messages.end()) {
+
+ logged_messages.emplace_back(hash);
+ log_to << message << std::endl;
+ return true;
+ }
+ return false;
}
DeprecatedHandlingMode get_deprecated_handling_mode()
@@ -174,9 +151,18 @@ DeprecatedHandlingMode get_deprecated_handling_mode()
return ret;
}
-void log_deprecated(lua_State *L, const std::string &message, int stack_depth)
+void log_deprecated(lua_State *L, std::string message, int stack_depth)
{
DeprecatedHandlingMode mode = get_deprecated_handling_mode();
- if (mode != DeprecatedHandlingMode::Ignore)
- script_log(L, message, warningstream, mode == DeprecatedHandlingMode::Error, stack_depth);
+ if (mode == DeprecatedHandlingMode::Ignore)
+ return;
+
+ script_log_add_source(L, message, stack_depth);
+ warningstream << message << std::endl;
+
+ if (mode == DeprecatedHandlingMode::Error)
+ script_error(L, LUA_ERRRUN, NULL, NULL);
+ else
+ infostream << script_get_backtrace(L) << std::endl;
}
+
diff --git a/src/script/common/c_internal.h b/src/script/common/c_internal.h
index 452c2dd5e..ab2d7b975 100644
--- a/src/script/common/c_internal.h
+++ b/src/script/common/c_internal.h
@@ -75,9 +75,6 @@ extern "C" {
} \
}
-#define script_run_callbacks(L, nargs, mode) \
- script_run_callbacks_f((L), (nargs), (mode), __FUNCTION__)
-
// What script_run_callbacks does with the return values of callbacks.
// Regardless of the mode, if only one callback is defined,
// its return value is the total return value.
@@ -108,13 +105,17 @@ enum RunCallbacksMode
// are converted by readParam<bool> to true or false, respectively.
};
+// Gets a backtrace of the current execution point
std::string script_get_backtrace(lua_State *L);
+// Wrapper for CFunction calls that converts C++ exceptions to Lua errors
int script_exception_wrapper(lua_State *L, lua_CFunction f);
+// Takes an error from lua_pcall and throws it as a LuaError
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,
- RunCallbacksMode mode, const char *fxn);
-enum class DeprecatedHandlingMode {
+bool script_log_unique(lua_State *L, std::string message, std::ostream &log_to,
+ int stack_depth = 1);
+
+enum DeprecatedHandlingMode {
Ignore,
Log,
Error
@@ -134,5 +135,4 @@ DeprecatedHandlingMode get_deprecated_handling_mode();
* @param message The deprecation method
* @param stack_depth How far on the stack to the first user function (ie: not builtin or core)
*/
-void log_deprecated(lua_State *L, const std::string &message,
- int stack_depth=1);
+void log_deprecated(lua_State *L, std::string message, int stack_depth = 1);
diff --git a/src/script/cpp_api/s_async.cpp b/src/script/cpp_api/s_async.cpp
index 0619b32c0..dacdcd75a 100644
--- a/src/script/cpp_api/s_async.cpp
+++ b/src/script/cpp_api/s_async.cpp
@@ -32,20 +32,19 @@ extern "C" {
#include "filesys.h"
#include "porting.h"
#include "common/c_internal.h"
+#include "lua_api/l_base.h"
/******************************************************************************/
AsyncEngine::~AsyncEngine()
{
-
// Request all threads to stop
for (AsyncWorkerThread *workerThread : workerThreads) {
workerThread->stop();
}
-
// Wake up all threads
- for (std::vector<AsyncWorkerThread *>::iterator it = workerThreads.begin();
- it != workerThreads.end(); ++it) {
+ for (auto it : workerThreads) {
+ (void)it;
jobQueueCounter.post();
}
@@ -68,6 +67,7 @@ AsyncEngine::~AsyncEngine()
/******************************************************************************/
void AsyncEngine::registerStateInitializer(StateInitializer func)
{
+ FATAL_ERROR_IF(initDone, "Initializer may not be registered after init");
stateInitializers.push_back(func);
}
@@ -85,36 +85,36 @@ void AsyncEngine::initialize(unsigned int numEngines)
}
/******************************************************************************/
-unsigned int AsyncEngine::queueAsyncJob(const std::string &func,
- const std::string &params)
+u32 AsyncEngine::queueAsyncJob(std::string &&func, std::string &&params,
+ const std::string &mod_origin)
{
jobQueueMutex.lock();
- LuaJobInfo toAdd;
- toAdd.id = jobIdCounter++;
- toAdd.serializedFunction = func;
- toAdd.serializedParams = params;
+ u32 jobId = jobIdCounter++;
- jobQueue.push_back(toAdd);
+ jobQueue.emplace_back();
+ auto &to_add = jobQueue.back();
+ to_add.id = jobId;
+ to_add.function = std::move(func);
+ to_add.params = std::move(params);
+ to_add.mod_origin = mod_origin;
jobQueueCounter.post();
-
jobQueueMutex.unlock();
-
- return toAdd.id;
+ return jobId;
}
/******************************************************************************/
-LuaJobInfo AsyncEngine::getJob()
+bool AsyncEngine::getJob(LuaJobInfo *job)
{
jobQueueCounter.wait();
jobQueueMutex.lock();
- LuaJobInfo retval;
+ bool retval = false;
if (!jobQueue.empty()) {
- retval = jobQueue.front();
+ *job = std::move(jobQueue.front());
jobQueue.pop_front();
- retval.valid = true;
+ retval = true;
}
jobQueueMutex.unlock();
@@ -122,10 +122,10 @@ LuaJobInfo AsyncEngine::getJob()
}
/******************************************************************************/
-void AsyncEngine::putJobResult(const LuaJobInfo &result)
+void AsyncEngine::putJobResult(LuaJobInfo &&result)
{
resultQueueMutex.lock();
- resultQueue.push_back(result);
+ resultQueue.emplace_back(std::move(result));
resultQueueMutex.unlock();
}
@@ -134,26 +134,30 @@ void AsyncEngine::step(lua_State *L)
{
int error_handler = PUSH_ERROR_HANDLER(L);
lua_getglobal(L, "core");
- resultQueueMutex.lock();
+
+ ScriptApiBase *script = ModApiBase::getScriptApiBase(L);
+
+ MutexAutoLock autolock(resultQueueMutex);
while (!resultQueue.empty()) {
- LuaJobInfo jobDone = resultQueue.front();
+ LuaJobInfo j = std::move(resultQueue.front());
resultQueue.pop_front();
lua_getfield(L, -1, "async_event_handler");
-
- if (lua_isnil(L, -1)) {
+ if (lua_isnil(L, -1))
FATAL_ERROR("Async event handler does not exist!");
- }
-
luaL_checktype(L, -1, LUA_TFUNCTION);
- lua_pushinteger(L, jobDone.id);
- lua_pushlstring(L, jobDone.serializedResult.data(),
- jobDone.serializedResult.size());
+ lua_pushinteger(L, j.id);
+ lua_pushlstring(L, j.result.data(), j.result.size());
- PCALL_RESL(L, lua_pcall(L, 2, 0, error_handler));
+ // Call handler
+ const char *origin = j.mod_origin.empty() ? nullptr : j.mod_origin.c_str();
+ script->setOriginDirect(origin);
+ int result = lua_pcall(L, 2, 0, error_handler);
+ if (result)
+ script_error(L, result, origin, "<async>");
}
- resultQueueMutex.unlock();
+
lua_pop(L, 2); // Pop core and error handler
}
@@ -168,8 +172,8 @@ void AsyncEngine::prepareEnvironment(lua_State* L, int top)
/******************************************************************************/
AsyncWorkerThread::AsyncWorkerThread(AsyncEngine* jobDispatcher,
const std::string &name) :
- Thread(name),
ScriptApiBase(ScriptingType::Async),
+ Thread(name),
jobDispatcher(jobDispatcher)
{
lua_State *L = getStack();
@@ -196,9 +200,9 @@ void* AsyncWorkerThread::run()
{
lua_State *L = getStack();
- std::string script = getServer()->getBuiltinLuaPath() + DIR_DELIM + "init.lua";
try {
- loadScript(script);
+ loadMod(getServer()->getBuiltinLuaPath() + DIR_DELIM + "init.lua",
+ BUILTIN_MOD_NAME);
} catch (const ModError &e) {
errorstream << "Execution of async base environment failed: "
<< e.what() << std::endl;
@@ -213,44 +217,44 @@ void* AsyncWorkerThread::run()
}
// Main loop
+ LuaJobInfo j;
while (!stopRequested()) {
// Wait for job
- LuaJobInfo toProcess = jobDispatcher->getJob();
-
- if (!toProcess.valid || stopRequested()) {
+ if (!jobDispatcher->getJob(&j) || stopRequested())
continue;
- }
lua_getfield(L, -1, "job_processor");
- if (lua_isnil(L, -1)) {
+ if (lua_isnil(L, -1))
FATAL_ERROR("Unable to get async job processor!");
- }
-
luaL_checktype(L, -1, LUA_TFUNCTION);
- // Call it
- lua_pushlstring(L,
- toProcess.serializedFunction.data(),
- toProcess.serializedFunction.size());
- lua_pushlstring(L,
- toProcess.serializedParams.data(),
- toProcess.serializedParams.size());
+ if (luaL_loadbuffer(L, j.function.data(), j.function.size(), "=(async)")) {
+ errorstream << "ASYNC WORKER: Unable to deserialize function" << std::endl;
+ lua_pushnil(L);
+ }
+ lua_pushlstring(L, j.params.data(), j.params.size());
+ // Call it
+ setOriginDirect(j.mod_origin.empty() ? nullptr : j.mod_origin.c_str());
int result = lua_pcall(L, 2, 1, error_handler);
if (result) {
- PCALL_RES(result);
- toProcess.serializedResult = "";
+ try {
+ scriptError(result, "<async>");
+ } catch (const ModError &e) {
+ errorstream << e.what() << std::endl;
+ }
} else {
// Fetch result
size_t length;
const char *retval = lua_tolstring(L, -1, &length);
- toProcess.serializedResult = std::string(retval, length);
+ j.result.assign(retval, length);
}
lua_pop(L, 1); // Pop retval
// Put job result
- jobDispatcher->putJobResult(toProcess);
+ if (!j.result.empty())
+ jobDispatcher->putJobResult(std::move(j));
}
lua_pop(L, 2); // Pop core and error handler
diff --git a/src/script/cpp_api/s_async.h b/src/script/cpp_api/s_async.h
index 99a4f891c..697cb0221 100644
--- a/src/script/cpp_api/s_async.h
+++ b/src/script/cpp_api/s_async.h
@@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <vector>
#include <deque>
-#include <map>
#include "threading/semaphore.h"
#include "threading/thread.h"
@@ -39,26 +38,29 @@ struct LuaJobInfo
{
LuaJobInfo() = default;
- // Function to be called in async environment
- std::string serializedFunction = "";
- // Parameter to be passed to function
- std::string serializedParams = "";
- // Result of function call
- std::string serializedResult = "";
+ // Function to be called in async environment (from string.dump)
+ std::string function;
+ // Parameter to be passed to function (serialized)
+ std::string params;
+ // Result of function call (serialized)
+ std::string result;
+ // Name of the mod who invoked this call
+ std::string mod_origin;
// JobID used to identify a job and match it to callback
- unsigned int id = 0;
-
- bool valid = false;
+ u32 id;
};
// Asynchronous working environment
-class AsyncWorkerThread : public Thread, public ScriptApiBase {
+class AsyncWorkerThread : public Thread, virtual public ScriptApiBase {
+ friend class AsyncEngine;
public:
- AsyncWorkerThread(AsyncEngine* jobDispatcher, const std::string &name);
virtual ~AsyncWorkerThread();
void *run();
+protected:
+ AsyncWorkerThread(AsyncEngine* jobDispatcher, const std::string &name);
+
private:
AsyncEngine *jobDispatcher = nullptr;
};
@@ -89,7 +91,8 @@ public:
* @param params Serialized parameters
* @return jobid The job is queued
*/
- unsigned int queueAsyncJob(const std::string &func, const std::string &params);
+ u32 queueAsyncJob(std::string &&func, std::string &&params,
+ const std::string &mod_origin = "");
/**
* Engine step to process finished jobs
@@ -102,15 +105,16 @@ protected:
/**
* Get a Job from queue to be processed
* this function blocks until a job is ready
- * @return a job to be processed
+ * @param job a job to be processed
+ * @return whether a job was available
*/
- LuaJobInfo getJob();
+ bool getJob(LuaJobInfo *job);
/**
* Put a Job result back to result queue
* @param result result of completed job
*/
- void putJobResult(const LuaJobInfo &result);
+ void putJobResult(LuaJobInfo &&result);
/**
* Initialize environment with current registred functions
@@ -129,11 +133,10 @@ private:
std::vector<StateInitializer> stateInitializers;
// Internal counter to create job IDs
- unsigned int jobIdCounter = 0;
+ u32 jobIdCounter = 0;
// Mutex to protect job queue
std::mutex jobQueueMutex;
-
// Job queue
std::deque<LuaJobInfo> jobQueue;
diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp
index 5711ccbfd..27d730b1d 100644
--- a/src/script/cpp_api/s_base.cpp
+++ b/src/script/cpp_api/s_base.cpp
@@ -332,13 +332,9 @@ void ScriptApiBase::setOriginDirect(const char *origin)
void ScriptApiBase::setOriginFromTableRaw(int index, const char *fxn)
{
-#ifdef SCRIPTAPI_DEBUG
lua_State *L = getStack();
-
m_last_run_mod = lua_istable(L, index) ?
getstringfield_default(L, index, "mod_origin", "") : "";
- //printf(">>>> running %s for mod: %s\n", fxn, m_last_run_mod.c_str());
-#endif
}
/*
diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h
index a7a2c7203..e49745f4e 100644
--- a/src/script/cpp_api/s_base.h
+++ b/src/script/cpp_api/s_base.h
@@ -39,7 +39,6 @@ extern "C" {
#include "config.h"
#define SCRIPTAPI_LOCK_DEBUG
-#define SCRIPTAPI_DEBUG
// MUST be an invalid mod name so that mods can't
// use that name to bypass security!
@@ -111,7 +110,9 @@ public:
Game *getGame() { return m_game; }
#endif
- std::string getOrigin() { return m_last_run_mod; }
+ // IMPORTANT: these cannot be used for any security-related uses, they exist
+ // only to enrich error messages
+ const std::string &getOrigin() { return m_last_run_mod; }
void setOriginDirect(const char *origin);
void setOriginFromTableRaw(int index, const char *fxn);
@@ -130,8 +131,11 @@ protected:
lua_State* getStack()
{ return m_luastack; }
+ // Checks that stack size is sane
void realityCheck();
+ // Takes an error from lua_pcall and throws it as a LuaError
void scriptError(int result, const char *fxn);
+ // Dumps stack contents for debugging
void stackDump(std::ostream &o);
void setGameDef(IGameDef* gamedef) { m_gamedef = gamedef; }
diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp
index 1ed273a30..5d20f547d 100644
--- a/src/script/cpp_api/s_client.cpp
+++ b/src/script/cpp_api/s_client.cpp
@@ -36,7 +36,11 @@ void ScriptApiClient::on_mods_loaded()
lua_getglobal(L, "core");
lua_getfield(L, -1, "registered_on_mods_loaded");
// Call callbacks
- runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
+ try {
+ runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ }
}
void ScriptApiClient::on_shutdown()
@@ -47,7 +51,11 @@ void ScriptApiClient::on_shutdown()
lua_getglobal(L, "core");
lua_getfield(L, -1, "registered_on_shutdown");
// Call callbacks
- runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
+ try {
+ runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ }
}
bool ScriptApiClient::on_sending_message(const std::string &message)
@@ -59,7 +67,12 @@ bool ScriptApiClient::on_sending_message(const std::string &message)
lua_getfield(L, -1, "registered_on_sending_chat_message");
// Call callbacks
lua_pushstring(L, message.c_str());
- runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+ try {
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ return true;
+ }
return readParam<bool>(L, -1);
}
@@ -72,7 +85,12 @@ bool ScriptApiClient::on_receiving_message(const std::string &message)
lua_getfield(L, -1, "registered_on_receiving_chat_message");
// Call callbacks
lua_pushstring(L, message.c_str());
- runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+ try {
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ return true;
+ }
return readParam<bool>(L, -1);
}
@@ -85,7 +103,11 @@ void ScriptApiClient::on_damage_taken(int32_t damage_amount)
lua_getfield(L, -1, "registered_on_damage_taken");
// Call callbacks
lua_pushinteger(L, damage_amount);
- runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+ try {
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ }
}
void ScriptApiClient::on_hp_modification(int32_t newhp)
@@ -97,7 +119,11 @@ void ScriptApiClient::on_hp_modification(int32_t newhp)
lua_getfield(L, -1, "registered_on_hp_modification");
// Call callbacks
lua_pushinteger(L, newhp);
- runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+ try {
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ }
}
void ScriptApiClient::on_death()
@@ -108,7 +134,11 @@ void ScriptApiClient::on_death()
lua_getglobal(L, "core");
lua_getfield(L, -1, "registered_on_death");
// Call callbacks
- runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
+ try {
+ runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ }
}
void ScriptApiClient::environment_step(float dtime)
@@ -123,8 +153,7 @@ void ScriptApiClient::environment_step(float dtime)
try {
runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
} catch (LuaError &e) {
- getClient()->setFatalError(std::string("Client environment_step: ") + e.what() + "\n"
- + script_get_backtrace(L));
+ getClient()->setFatalError(e);
}
}
@@ -149,7 +178,11 @@ void ScriptApiClient::on_formspec_input(const std::string &formname,
lua_pushlstring(L, value.c_str(), value.size());
lua_settable(L, -3);
}
- runCallbacks(2, RUN_CALLBACKS_MODE_OR_SC);
+ try {
+ runCallbacks(2, RUN_CALLBACKS_MODE_OR_SC);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ }
}
bool ScriptApiClient::on_dignode(v3s16 p, MapNode node)
@@ -167,7 +200,12 @@ bool ScriptApiClient::on_dignode(v3s16 p, MapNode node)
pushnode(L, node, ndef);
// Call functions
- runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ try {
+ runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ return true;
+ }
return lua_toboolean(L, -1);
}
@@ -186,7 +224,12 @@ bool ScriptApiClient::on_punchnode(v3s16 p, MapNode node)
pushnode(L, node, ndef);
// Call functions
- runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ try {
+ runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ return true;
+ }
return readParam<bool>(L, -1);
}
@@ -203,7 +246,12 @@ bool ScriptApiClient::on_placenode(const PointedThing &pointed, const ItemDefini
push_item_definition(L, item);
// Call functions
- runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ try {
+ runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ return true;
+ }
return readParam<bool>(L, -1);
}
@@ -220,7 +268,12 @@ bool ScriptApiClient::on_item_use(const ItemStack &item, const PointedThing &poi
push_pointed_thing(L, pointed, true);
// Call functions
- runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ try {
+ runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ return true;
+ }
return readParam<bool>(L, -1);
}
@@ -348,7 +401,12 @@ bool ScriptApiClient::on_inventory_open(Inventory *inventory)
push_inventory(L, inventory);
- runCallbacks(1, RUN_CALLBACKS_MODE_OR);
+ try {
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(e);
+ return true;
+ }
return readParam<bool>(L, -1);
}
diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp
index 8da5debaa..874c37b6e 100644
--- a/src/script/cpp_api/s_env.cpp
+++ b/src/script/cpp_api/s_env.cpp
@@ -25,6 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapgen/mapgen.h"
#include "lua_api/l_env.h"
#include "server.h"
+#include "script/common/c_content.h"
+
void ScriptApiEnv::environment_OnGenerated(v3s16 minp, v3s16 maxp,
u32 blockseed)
@@ -51,13 +53,7 @@ void ScriptApiEnv::environment_Step(float dtime)
lua_getfield(L, -1, "registered_globalsteps");
// Call callbacks
lua_pushnumber(L, dtime);
- try {
- runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
- } catch (LuaError &e) {
- getServer()->setAsyncFatalError(
- std::string("environment_Step: ") + e.what() + "\n"
- + script_get_backtrace(L));
- }
+ runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
}
void ScriptApiEnv::player_event(ServerActiveObject *player, const std::string &type)
@@ -74,13 +70,7 @@ void ScriptApiEnv::player_event(ServerActiveObject *player, const std::string &t
// Call callbacks
objectrefGetOrCreate(L, player); // player
lua_pushstring(L,type.c_str()); // event type
- try {
- runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
- } catch (LuaError &e) {
- getServer()->setAsyncFatalError(
- std::string("player_event: ") + e.what() + "\n"
- + script_get_backtrace(L) );
- }
+ runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
}
void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env)
@@ -150,13 +140,19 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env)
bool simple_catch_up = true;
getboolfield(L, current_abm, "catch_up", simple_catch_up);
+
+ s16 min_y = INT16_MIN;
+ getintfield(L, current_abm, "min_y", min_y);
+
+ s16 max_y = INT16_MAX;
+ getintfield(L, current_abm, "max_y", max_y);
lua_getfield(L, current_abm, "action");
luaL_checktype(L, current_abm + 1, LUA_TFUNCTION);
lua_pop(L, 1);
LuaABM *abm = new LuaABM(L, id, trigger_contents, required_neighbors,
- trigger_interval, trigger_chance, simple_catch_up);
+ trigger_interval, trigger_chance, simple_catch_up, min_y, max_y);
env->addActiveBlockModifier(abm);
@@ -249,9 +245,8 @@ void ScriptApiEnv::on_emerge_area_completion(
try {
PCALL_RES(lua_pcall(L, 4, 0, error_handler));
} catch (LuaError &e) {
- server->setAsyncFatalError(
- std::string("on_emerge_area_completion: ") + e.what() + "\n"
- + script_get_backtrace(L));
+ // Note: don't throw here, we still need to run the cleanup code below
+ server->setAsyncFatalError(e);
}
lua_pop(L, 1); // Pop error handler
@@ -261,3 +256,35 @@ void ScriptApiEnv::on_emerge_area_completion(
luaL_unref(L, LUA_REGISTRYINDEX, state->args_ref);
}
}
+
+void ScriptApiEnv::on_liquid_transformed(
+ const std::vector<std::pair<v3s16, MapNode>> &list)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_liquid_transformed
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_liquid_transformed");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ lua_remove(L, -2);
+
+ // Skip converting list and calling hook if there are
+ // no registered callbacks.
+ if(lua_objlen(L, -1) < 1) return;
+
+ // Convert the list to a pos array and a node array for lua
+ int index = 1;
+ const NodeDefManager *ndef = getEnv()->getGameDef()->ndef();
+ lua_createtable(L, list.size(), 0);
+ lua_createtable(L, list.size(), 0);
+ for(std::pair<v3s16, MapNode> p : list) {
+ lua_pushnumber(L, index);
+ push_v3s16(L, p.first);
+ lua_rawset(L, -4);
+ lua_pushnumber(L, index++);
+ pushnode(L, p.second, ndef);
+ lua_rawset(L, -3);
+ }
+
+ runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
+}
diff --git a/src/script/cpp_api/s_env.h b/src/script/cpp_api/s_env.h
index 232a08aaf..090858f17 100644
--- a/src/script/cpp_api/s_env.h
+++ b/src/script/cpp_api/s_env.h
@@ -21,6 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "cpp_api/s_base.h"
#include "irr_v3d.h"
+#include "mapnode.h"
+#include <vector>
class ServerEnvironment;
struct ScriptCallbackState;
@@ -41,5 +43,8 @@ public:
void on_emerge_area_completion(v3s16 blockpos, int action,
ScriptCallbackState *state);
+ // Called after liquid transform changes
+ void on_liquid_transformed(const std::vector<std::pair<v3s16, MapNode>> &list);
+
void initializeEnvironment(ServerEnvironment *env);
};
diff --git a/src/script/cpp_api/s_item.cpp b/src/script/cpp_api/s_item.cpp
index 24955cefc..48dce14f3 100644
--- a/src/script/cpp_api/s_item.cpp
+++ b/src/script/cpp_api/s_item.cpp
@@ -29,6 +29,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "inventory.h"
#include "inventorymanager.h"
+#define WRAP_LUAERROR(e, detail) \
+ LuaError(std::string(__FUNCTION__) + ": " + (e).what() + ". " detail)
+
bool ScriptApiItem::item_OnDrop(ItemStack &item,
ServerActiveObject *dropper, v3f pos)
{
@@ -49,7 +52,7 @@ bool ScriptApiItem::item_OnDrop(ItemStack &item,
try {
item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
- throw LuaError(std::string(e.what()) + ". item=" + item.name);
+ throw WRAP_LUAERROR(e, "item=" + item.name);
}
}
lua_pop(L, 2); // Pop item and error handler
@@ -81,7 +84,7 @@ bool ScriptApiItem::item_OnPlace(ItemStack &item,
try {
item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
- throw LuaError(std::string(e.what()) + ". item=" + item.name);
+ throw WRAP_LUAERROR(e, "item=" + item.name);
}
}
lua_pop(L, 2); // Pop item and error handler
@@ -108,7 +111,7 @@ bool ScriptApiItem::item_OnUse(ItemStack &item,
try {
item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
- throw LuaError(std::string(e.what()) + ". item=" + item.name);
+ throw WRAP_LUAERROR(e, "item=" + item.name);
}
}
lua_pop(L, 2); // Pop item and error handler
@@ -133,7 +136,7 @@ bool ScriptApiItem::item_OnSecondaryUse(ItemStack &item,
try {
item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
- throw LuaError(std::string(e.what()) + ". item=" + item.name);
+ throw WRAP_LUAERROR(e, "item=" + item.name);
}
}
lua_pop(L, 2); // Pop item and error handler
@@ -165,7 +168,7 @@ bool ScriptApiItem::item_OnCraft(ItemStack &item, ServerActiveObject *user,
try {
item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
- throw LuaError(std::string(e.what()) + ". item=" + item.name);
+ throw WRAP_LUAERROR(e, "item=" + item.name);
}
}
lua_pop(L, 2); // Pop item and error handler
@@ -197,7 +200,7 @@ bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user,
try {
item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
- throw LuaError(std::string(e.what()) + ". item=" + item.name);
+ throw WRAP_LUAERROR(e, "item=" + item.name);
}
}
lua_pop(L, 2); // Pop item and error handler
diff --git a/src/script/cpp_api/s_mainmenu.h b/src/script/cpp_api/s_mainmenu.h
index aef36ce39..470577a29 100644
--- a/src/script/cpp_api/s_mainmenu.h
+++ b/src/script/cpp_api/s_mainmenu.h
@@ -38,7 +38,7 @@ public:
void handleMainMenuEvent(std::string text);
/**
- * process field data recieved from formspec
+ * process field data received from formspec
* @param fields data in field format
*/
void handleMainMenuButtons(const StringMap &fields);
diff --git a/src/script/cpp_api/s_nodemeta.cpp b/src/script/cpp_api/s_nodemeta.cpp
index c081e9fc4..7ab3757f3 100644
--- a/src/script/cpp_api/s_nodemeta.cpp
+++ b/src/script/cpp_api/s_nodemeta.cpp
@@ -43,7 +43,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowMove(
return 0;
// Push callback function on stack
- std::string nodename = ndef->get(node).name;
+ const auto &nodename = ndef->get(node).name;
if (!getItemCallback(nodename.c_str(), "allow_metadata_inventory_move", &ma.to_inv.p))
return count;
@@ -58,7 +58,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowMove(
PCALL_RES(lua_pcall(L, 7, 1, error_handler));
if (!lua_isnumber(L, -1))
throw LuaError("allow_metadata_inventory_move should"
- " return a number, guilty node: " + nodename);
+ " return a number. node=" + nodename);
int num = luaL_checkinteger(L, -1);
lua_pop(L, 2); // Pop integer and error handler
return num;
@@ -81,7 +81,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowPut(
return 0;
// Push callback function on stack
- std::string nodename = ndef->get(node).name;
+ const auto &nodename = ndef->get(node).name;
if (!getItemCallback(nodename.c_str(), "allow_metadata_inventory_put", &ma.to_inv.p))
return stack.count;
@@ -94,7 +94,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowPut(
PCALL_RES(lua_pcall(L, 5, 1, error_handler));
if(!lua_isnumber(L, -1))
throw LuaError("allow_metadata_inventory_put should"
- " return a number, guilty node: " + nodename);
+ " return a number. node=" + nodename);
int num = luaL_checkinteger(L, -1);
lua_pop(L, 2); // Pop integer and error handler
return num;
@@ -117,7 +117,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowTake(
return 0;
// Push callback function on stack
- std::string nodename = ndef->get(node).name;
+ const auto &nodename = ndef->get(node).name;
if (!getItemCallback(nodename.c_str(), "allow_metadata_inventory_take", &ma.from_inv.p))
return stack.count;
@@ -130,7 +130,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowTake(
PCALL_RES(lua_pcall(L, 5, 1, error_handler));
if (!lua_isnumber(L, -1))
throw LuaError("allow_metadata_inventory_take should"
- " return a number, guilty node: " + nodename);
+ " return a number. node=" + nodename);
int num = luaL_checkinteger(L, -1);
lua_pop(L, 2); // Pop integer and error handler
return num;
@@ -153,7 +153,7 @@ void ScriptApiNodemeta::nodemeta_inventory_OnMove(
return;
// Push callback function on stack
- std::string nodename = ndef->get(node).name;
+ const auto &nodename = ndef->get(node).name;
if (!getItemCallback(nodename.c_str(), "on_metadata_inventory_move", &ma.from_inv.p))
return;
@@ -186,7 +186,7 @@ void ScriptApiNodemeta::nodemeta_inventory_OnPut(
return;
// Push callback function on stack
- std::string nodename = ndef->get(node).name;
+ const auto &nodename = ndef->get(node).name;
if (!getItemCallback(nodename.c_str(), "on_metadata_inventory_put", &ma.to_inv.p))
return;
@@ -217,7 +217,7 @@ void ScriptApiNodemeta::nodemeta_inventory_OnTake(
return;
// Push callback function on stack
- std::string nodename = ndef->get(node).name;
+ const auto &nodename = ndef->get(node).name;
if (!getItemCallback(nodename.c_str(), "on_metadata_inventory_take", &ma.from_inv.p))
return;
diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp
index 8fe5d2c5a..bd9c80e15 100644
--- a/src/script/cpp_api/s_security.cpp
+++ b/src/script/cpp_api/s_security.cpp
@@ -18,7 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "cpp_api/s_security.h"
-
+#include "lua_api/l_base.h"
#include "filesys.h"
#include "porting.h"
#include "server.h"
@@ -541,15 +541,8 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
if (!removed.empty())
abs_path += DIR_DELIM + removed;
- // Get server from registry
- lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
- ScriptApiBase *script;
-#if INDIRECT_SCRIPTAPI_RIDX
- script = (ScriptApiBase *) *(void**)(lua_touserdata(L, -1));
-#else
- script = (ScriptApiBase *) lua_touserdata(L, -1);
-#endif
- lua_pop(L, 1);
+ // Get gamedef from registry
+ ScriptApiBase *script = ModApiBase::getScriptApiBase(L);
const IGameDef *gamedef = script->getGameDef();
if (!gamedef)
return false;
@@ -672,13 +665,7 @@ int ScriptApiSecurity::sl_g_load(lua_State *L)
int ScriptApiSecurity::sl_g_loadfile(lua_State *L)
{
#ifndef SERVER
- lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
-#if INDIRECT_SCRIPTAPI_RIDX
- ScriptApiBase *script = (ScriptApiBase *) *(void**)(lua_touserdata(L, -1));
-#else
- ScriptApiBase *script = (ScriptApiBase *) lua_touserdata(L, -1);
-#endif
- lua_pop(L, 1);
+ ScriptApiBase *script = ModApiBase::getScriptApiBase(L);
// Client implementation
if (script->getType() == ScriptingType::Client) {
diff --git a/src/script/cpp_api/s_server.cpp b/src/script/cpp_api/s_server.cpp
index 96cb28b28..6ddb2630d 100644
--- a/src/script/cpp_api/s_server.cpp
+++ b/src/script/cpp_api/s_server.cpp
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "cpp_api/s_server.h"
#include "cpp_api/s_internal.h"
#include "common/c_converter.h"
+#include "util/numeric.h" // myrand
bool ScriptApiServer::getAuth(const std::string &playername,
std::string *dst_password,
@@ -196,3 +197,68 @@ std::string ScriptApiServer::formatChatMessage(const std::string &name,
return ret;
}
+
+u32 ScriptApiServer::allocateDynamicMediaCallback(int f_idx)
+{
+ lua_State *L = getStack();
+
+ if (f_idx < 0)
+ f_idx = lua_gettop(L) + f_idx + 1;
+
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "dynamic_media_callbacks");
+ luaL_checktype(L, -1, LUA_TTABLE);
+
+ // Find a randomly generated token that doesn't exist yet
+ int tries = 100;
+ u32 token;
+ while (1) {
+ token = myrand();
+ lua_rawgeti(L, -2, token);
+ bool is_free = lua_isnil(L, -1);
+ lua_pop(L, 1);
+ if (is_free)
+ break;
+ if (--tries < 0)
+ FATAL_ERROR("Ran out of callbacks IDs?!");
+ }
+
+ // core.dynamic_media_callbacks[token] = callback_func
+ lua_pushvalue(L, f_idx);
+ lua_rawseti(L, -2, token);
+
+ lua_pop(L, 2);
+
+ verbosestream << "allocateDynamicMediaCallback() = " << token << std::endl;
+ return token;
+}
+
+void ScriptApiServer::freeDynamicMediaCallback(u32 token)
+{
+ lua_State *L = getStack();
+
+ verbosestream << "freeDynamicMediaCallback(" << token << ")" << std::endl;
+
+ // core.dynamic_media_callbacks[token] = nil
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "dynamic_media_callbacks");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ lua_pushnil(L);
+ lua_rawseti(L, -2, token);
+ lua_pop(L, 2);
+}
+
+void ScriptApiServer::on_dynamic_media_added(u32 token, const char *playername)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ int error_handler = PUSH_ERROR_HANDLER(L);
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "dynamic_media_callbacks");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ lua_rawgeti(L, -1, token);
+ luaL_checktype(L, -1, LUA_TFUNCTION);
+
+ lua_pushstring(L, playername);
+ PCALL_RES(lua_pcall(L, 1, 0, error_handler));
+}
diff --git a/src/script/cpp_api/s_server.h b/src/script/cpp_api/s_server.h
index d8639cba7..c5c3d5596 100644
--- a/src/script/cpp_api/s_server.h
+++ b/src/script/cpp_api/s_server.h
@@ -49,6 +49,12 @@ public:
const std::string &password);
bool setPassword(const std::string &playername,
const std::string &password);
+
+ /* dynamic media handling */
+ u32 allocateDynamicMediaCallback(int f_idx);
+ void freeDynamicMediaCallback(u32 token);
+ void on_dynamic_media_added(u32 token, const char *playername);
+
private:
void getAuthHandler();
void readPrivileges(int index, std::set<std::string> &result);
diff --git a/src/script/lua_api/l_areastore.cpp b/src/script/lua_api/l_areastore.cpp
index 908c766b0..45724e604 100644
--- a/src/script/lua_api/l_areastore.cpp
+++ b/src/script/lua_api/l_areastore.cpp
@@ -372,7 +372,7 @@ void LuaAreaStore::Register(lua_State *L)
lua_pop(L, 1); // drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // drop methodtable
// Can be created from Lua (AreaStore())
diff --git a/src/script/lua_api/l_auth.cpp b/src/script/lua_api/l_auth.cpp
index 0fc57ba3a..32d8a7411 100644
--- a/src/script/lua_api/l_auth.cpp
+++ b/src/script/lua_api/l_auth.cpp
@@ -32,8 +32,11 @@ AuthDatabase *ModApiAuth::getAuthDb(lua_State *L)
{
ServerEnvironment *server_environment =
dynamic_cast<ServerEnvironment *>(getEnv(L));
- if (!server_environment)
+ if (!server_environment) {
+ luaL_error(L, "Attempt to access an auth function but the auth"
+ " system is yet not initialized. This causes bugs.");
return nullptr;
+ }
return server_environment->getAuthDatabase();
}
diff --git a/src/script/lua_api/l_camera.cpp b/src/script/lua_api/l_camera.cpp
index 40251154c..d85d16283 100644
--- a/src/script/lua_api/l_camera.cpp
+++ b/src/script/lua_api/l_camera.cpp
@@ -219,7 +219,7 @@ void LuaCamera::Register(lua_State *L)
lua_pop(L, 1);
- luaL_openlib(L, 0, methods, 0);
+ luaL_register(L, nullptr, methods);
lua_pop(L, 1);
}
diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp
index d6dc79ca8..74db996a4 100644
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -46,13 +46,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/client.h"
#endif
-struct EnumString ModApiEnvMod::es_ClearObjectsMode[] =
+const EnumString ModApiEnvMod::es_ClearObjectsMode[] =
{
{CLEAR_OBJECTS_MODE_FULL, "full"},
{CLEAR_OBJECTS_MODE_QUICK, "quick"},
{0, NULL},
};
+const EnumString ModApiEnvMod::es_BlockStatusType[] =
+{
+ {ServerEnvironment::BS_UNKNOWN, "unknown"},
+ {ServerEnvironment::BS_EMERGING, "emerging"},
+ {ServerEnvironment::BS_LOADED, "loaded"},
+ {ServerEnvironment::BS_ACTIVE, "active"},
+ {0, NULL},
+};
+
///////////////////////////////////////////////////////////////////////////////
@@ -228,7 +237,7 @@ void LuaRaycast::Register(lua_State *L)
lua_pop(L, 1);
- luaL_openlib(L, 0, methods, 0);
+ luaL_register(L, nullptr, methods);
lua_pop(L, 1);
lua_register(L, className, create_object);
@@ -1547,6 +1556,24 @@ int ModApiEnvMod::l_forceload_block(lua_State *L)
return 0;
}
+// compare_block_status(nodepos)
+int ModApiEnvMod::l_compare_block_status(lua_State *L)
+{
+ GET_ENV_PTR;
+
+ v3s16 nodepos = check_v3s16(L, 1);
+ std::string condition_s = luaL_checkstring(L, 2);
+ auto status = env->getBlockStatus(getNodeBlockPos(nodepos));
+
+ int condition_i = -1;
+ if (!string_to_enum(es_BlockStatusType, condition_i, condition_s))
+ return 0; // Unsupported
+
+ lua_pushboolean(L, status >= condition_i);
+ return 1;
+}
+
+
// forceload_free_block(blockpos)
// blockpos = {x=num, y=num, z=num}
int ModApiEnvMod::l_forceload_free_block(lua_State *L)
@@ -1620,6 +1647,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
API_FCT(transforming_liquid_add);
API_FCT(forceload_block);
API_FCT(forceload_free_block);
+ API_FCT(compare_block_status);
API_FCT(get_translated_string);
}
diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h
index 29044c0e8..a5ac21e21 100644
--- a/src/script/lua_api/l_env.h
+++ b/src/script/lua_api/l_env.h
@@ -207,6 +207,9 @@ private:
// stops forceloading a position
static int l_forceload_free_block(lua_State *L);
+ // compare_block_status(nodepos)
+ static int l_compare_block_status(lua_State *L);
+
// Get a string translated server side
static int l_get_translated_string(lua_State * L);
@@ -219,7 +222,8 @@ public:
static void Initialize(lua_State *L, int top);
static void InitializeClient(lua_State *L, int top);
- static struct EnumString es_ClearObjectsMode[];
+ static const EnumString es_ClearObjectsMode[];
+ static const EnumString es_BlockStatusType[];
};
class LuaABM : public ActiveBlockModifier {
@@ -231,17 +235,21 @@ private:
float m_trigger_interval;
u32 m_trigger_chance;
bool m_simple_catch_up;
+ s16 m_min_y;
+ s16 m_max_y;
public:
LuaABM(lua_State *L, int id,
const std::vector<std::string> &trigger_contents,
const std::vector<std::string> &required_neighbors,
- float trigger_interval, u32 trigger_chance, bool simple_catch_up):
+ float trigger_interval, u32 trigger_chance, bool simple_catch_up, s16 min_y, s16 max_y):
m_id(id),
m_trigger_contents(trigger_contents),
m_required_neighbors(required_neighbors),
m_trigger_interval(trigger_interval),
m_trigger_chance(trigger_chance),
- m_simple_catch_up(simple_catch_up)
+ m_simple_catch_up(simple_catch_up),
+ m_min_y(min_y),
+ m_max_y(max_y)
{
}
virtual const std::vector<std::string> &getTriggerContents() const
@@ -264,6 +272,14 @@ public:
{
return m_simple_catch_up;
}
+ virtual s16 getMinY()
+ {
+ return m_min_y;
+ }
+ virtual s16 getMaxY()
+ {
+ return m_max_y;
+ }
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
u32 active_object_count, u32 active_object_count_wider);
};
diff --git a/src/script/lua_api/l_http.cpp b/src/script/lua_api/l_http.cpp
index 5ea3b3f99..751ec9837 100644
--- a/src/script/lua_api/l_http.cpp
+++ b/src/script/lua_api/l_http.cpp
@@ -42,12 +42,10 @@ void ModApiHttp::read_http_fetch_request(lua_State *L, HTTPFetchRequest &req)
req.caller = httpfetch_caller_alloc_secure();
getstringfield(L, 1, "url", req.url);
- lua_getfield(L, 1, "user_agent");
- if (lua_isstring(L, -1))
- req.useragent = getstringfield_default(L, 1, "user_agent", "");
- lua_pop(L, 1);
+ getstringfield(L, 1, "user_agent", req.useragent);
req.multipart = getboolfield_default(L, 1, "multipart", false);
- req.timeout = getintfield_default(L, 1, "timeout", 3) * 1000;
+ if (getintfield(L, 1, "timeout", req.timeout))
+ req.timeout *= 1000;
lua_getfield(L, 1, "method");
if (lua_isstring(L, -1)) {
diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp
index 434d0a76c..0dd418462 100644
--- a/src/script/lua_api/l_inventory.cpp
+++ b/src/script/lua_api/l_inventory.cpp
@@ -456,7 +456,7 @@ void InvRef::Register(lua_State *L)
lua_pop(L, 1); // drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // drop methodtable
// Cannot be created from Lua
diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp
index b098eccf0..2ea2bd4f6 100644
--- a/src/script/lua_api/l_item.cpp
+++ b/src/script/lua_api/l_item.cpp
@@ -488,7 +488,7 @@ void LuaItemStack::Register(lua_State *L)
lua_pop(L, 1); // drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // drop methodtable
// Can be created from Lua (ItemStack(itemstack or itemstring or table or nil))
diff --git a/src/script/lua_api/l_itemstackmeta.cpp b/src/script/lua_api/l_itemstackmeta.cpp
index d1ba1bda4..739fb9221 100644
--- a/src/script/lua_api/l_itemstackmeta.cpp
+++ b/src/script/lua_api/l_itemstackmeta.cpp
@@ -114,7 +114,7 @@ void ItemStackMetaRef::Register(lua_State *L)
lua_pop(L, 1); // drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // drop methodtable
// Cannot be created from Lua
diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp
index 4f57ee00f..769b3ef2b 100644
--- a/src/script/lua_api/l_localplayer.cpp
+++ b/src/script/lua_api/l_localplayer.cpp
@@ -295,16 +295,20 @@ int LuaLocalPlayer::l_get_control(lua_State *L)
};
lua_createtable(L, 0, 12);
- set("up", c.up);
- set("down", c.down);
- set("left", c.left);
- set("right", c.right);
- set("jump", c.jump);
- set("aux1", c.aux1);
+ set("jump", c.jump);
+ set("aux1", c.aux1);
set("sneak", c.sneak);
- set("zoom", c.zoom);
- set("dig", c.dig);
+ set("zoom", c.zoom);
+ set("dig", c.dig);
set("place", c.place);
+ // Player movement in polar coordinates and non-binary speed
+ set("movement_speed", c.movement_speed);
+ set("movement_direction", c.movement_direction);
+ // Provide direction keys to ensure compatibility
+ set("up", player->keyPressed & (1 << 0)); // Up, down, left, and right were removed in favor of
+ set("down", player->keyPressed & (1 << 1)); // analog direction indicators and are therefore not
+ set("left", player->keyPressed & (1 << 2)); // available as booleans anymore. The corresponding values
+ set("right", player->keyPressed & (1 << 3)); // can still be read from the keyPressed bits though.
return 1;
}
@@ -452,10 +456,11 @@ int LuaLocalPlayer::l_hud_change(lua_State *L)
if (!element)
return 0;
+ HudElementStat stat;
void *unused;
- read_hud_change(L, element, &unused);
+ bool ok = read_hud_change(L, stat, element, &unused);
- lua_pushboolean(L, true);
+ lua_pushboolean(L, ok);
return 1;
}
@@ -550,7 +555,7 @@ void LuaLocalPlayer::Register(lua_State *L)
lua_pop(L, 1); // Drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // Drop methodtable
}
diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp
index d88bf31c1..8eb0e252a 100644
--- a/src/script/lua_api/l_mainmenu.cpp
+++ b/src/script/lua_api/l_mainmenu.cpp
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_internal.h"
#include "common/c_content.h"
#include "cpp_api/s_async.h"
+#include "scripting_mainmenu.h"
#include "gui/guiEngine.h"
#include "gui/guiMainMenu.h"
#include "gui/guiKeyChangeMenu.h"
@@ -741,13 +742,12 @@ int ModApiMainMenu::l_get_video_drivers(lua_State *L)
lua_newtable(L);
for (u32 i = 0; i != drivers.size(); i++) {
- const char *name = RenderingEngine::getVideoDriverName(drivers[i]);
- const char *fname = RenderingEngine::getVideoDriverFriendlyName(drivers[i]);
+ auto &info = RenderingEngine::getVideoDriverInfo(drivers[i]);
lua_newtable(L);
- lua_pushstring(L, name);
+ lua_pushstring(L, info.name.c_str());
lua_setfield(L, -2, "name");
- lua_pushstring(L, fname);
+ lua_pushstring(L, info.friendly_name.c_str());
lua_setfield(L, -2, "friendly_name");
lua_rawseti(L, -2, i + 1);
@@ -757,28 +757,6 @@ int ModApiMainMenu::l_get_video_drivers(lua_State *L)
}
/******************************************************************************/
-int ModApiMainMenu::l_get_video_modes(lua_State *L)
-{
- std::vector<core::vector3d<u32> > videomodes
- = RenderingEngine::getSupportedVideoModes();
-
- lua_newtable(L);
- for (u32 i = 0; i != videomodes.size(); i++) {
- lua_newtable(L);
- lua_pushnumber(L, videomodes[i].X);
- lua_setfield(L, -2, "w");
- lua_pushnumber(L, videomodes[i].Y);
- lua_setfield(L, -2, "h");
- lua_pushnumber(L, videomodes[i].Z);
- lua_setfield(L, -2, "depth");
-
- lua_rawseti(L, -2, i + 1);
- }
-
- return 1;
-}
-
-/******************************************************************************/
int ModApiMainMenu::l_gettext(lua_State *L)
{
std::string text = strgettext(std::string(luaL_checkstring(L, 1)));
@@ -843,20 +821,20 @@ int ModApiMainMenu::l_open_dir(lua_State *L)
/******************************************************************************/
int ModApiMainMenu::l_do_async_callback(lua_State *L)
{
- GUIEngine* engine = getGuiEngine(L);
+ MainMenuScripting *script = getScriptApi<MainMenuScripting>(L);
size_t func_length, param_length;
const char* serialized_func_raw = luaL_checklstring(L, 1, &func_length);
-
const char* serialized_param_raw = luaL_checklstring(L, 2, &param_length);
sanity_check(serialized_func_raw != NULL);
sanity_check(serialized_param_raw != NULL);
- std::string serialized_func = std::string(serialized_func_raw, func_length);
- std::string serialized_param = std::string(serialized_param_raw, param_length);
+ u32 jobId = script->queueAsync(
+ std::string(serialized_func_raw, func_length),
+ std::string(serialized_param_raw, param_length));
- lua_pushinteger(L, engine->queueAsync(serialized_func, serialized_param));
+ lua_pushinteger(L, jobId);
return 1;
}
@@ -899,7 +877,6 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
API_FCT(download_file);
API_FCT(gettext);
API_FCT(get_video_drivers);
- API_FCT(get_video_modes);
API_FCT(get_screen_info);
API_FCT(get_min_supp_proto);
API_FCT(get_max_supp_proto);
diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h
index 33ac9e721..ec2d20da2 100644
--- a/src/script/lua_api/l_mainmenu.h
+++ b/src/script/lua_api/l_mainmenu.h
@@ -140,8 +140,6 @@ private:
static int l_get_video_drivers(lua_State *L);
- static int l_get_video_modes(lua_State *L);
-
//version compatibility
static int l_get_min_supp_proto(lua_State *L);
diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp
index eb3d49a5e..f173bd162 100644
--- a/src/script/lua_api/l_mapgen.cpp
+++ b/src/script/lua_api/l_mapgen.cpp
@@ -752,9 +752,7 @@ int ModApiMapgen::l_get_mapgen_params(lua_State *L)
lua_setfield(L, -2, "mgname");
settingsmgr->getMapSetting("seed", &value);
- std::istringstream ss(value);
- u64 seed;
- ss >> seed;
+ u64 seed = from_string<u64>(value);
lua_pushinteger(L, seed);
lua_setfield(L, -2, "seed");
diff --git a/src/script/lua_api/l_minimap.cpp b/src/script/lua_api/l_minimap.cpp
index 3bbb6e5e3..a135e0bd5 100644
--- a/src/script/lua_api/l_minimap.cpp
+++ b/src/script/lua_api/l_minimap.cpp
@@ -211,7 +211,7 @@ void LuaMinimap::Register(lua_State *L)
lua_pop(L, 1); // drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // drop methodtable
}
diff --git a/src/script/lua_api/l_modchannels.cpp b/src/script/lua_api/l_modchannels.cpp
index 0485b276a..931c2749c 100644
--- a/src/script/lua_api/l_modchannels.cpp
+++ b/src/script/lua_api/l_modchannels.cpp
@@ -107,7 +107,7 @@ void ModChannelRef::Register(lua_State *L)
lua_pop(L, 1); // Drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // Drop methodtable
}
diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp
index 57052cb42..60d14f8f2 100644
--- a/src/script/lua_api/l_nodemeta.cpp
+++ b/src/script/lua_api/l_nodemeta.cpp
@@ -234,7 +234,7 @@ void NodeMetaRef::RegisterCommon(lua_State *L)
void NodeMetaRef::Register(lua_State *L)
{
RegisterCommon(L);
- luaL_openlib(L, 0, methodsServer, 0); // fill methodtable
+ luaL_register(L, nullptr, methodsServer); // fill methodtable
lua_pop(L, 1); // drop methodtable
}
@@ -260,7 +260,7 @@ const luaL_Reg NodeMetaRef::methodsServer[] = {
void NodeMetaRef::RegisterClient(lua_State *L)
{
RegisterCommon(L);
- luaL_openlib(L, 0, methodsClient, 0); // fill methodtable
+ luaL_register(L, nullptr, methodsClient); // fill methodtable
lua_pop(L, 1); // drop methodtable
}
diff --git a/src/script/lua_api/l_nodetimer.cpp b/src/script/lua_api/l_nodetimer.cpp
index c2df52c05..8a302149f 100644
--- a/src/script/lua_api/l_nodetimer.cpp
+++ b/src/script/lua_api/l_nodetimer.cpp
@@ -122,7 +122,7 @@ void NodeTimerRef::Register(lua_State *L)
lua_pop(L, 1); // drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // drop methodtable
// Cannot be created from Lua
diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp
index e0861126a..f43ba837a 100644
--- a/src/script/lua_api/l_noise.cpp
+++ b/src/script/lua_api/l_noise.cpp
@@ -122,7 +122,7 @@ void LuaPerlinNoise::Register(lua_State *L)
lua_pop(L, 1);
- luaL_openlib(L, 0, methods, 0);
+ luaL_register(L, nullptr, methods);
lua_pop(L, 1);
lua_register(L, className, create_object);
@@ -380,7 +380,7 @@ void LuaPerlinNoiseMap::Register(lua_State *L)
lua_pop(L, 1);
- luaL_openlib(L, 0, methods, 0);
+ luaL_register(L, nullptr, methods);
lua_pop(L, 1);
lua_register(L, className, create_object);
@@ -485,7 +485,7 @@ void LuaPseudoRandom::Register(lua_State *L)
lua_pop(L, 1);
- luaL_openlib(L, 0, methods, 0);
+ luaL_register(L, nullptr, methods);
lua_pop(L, 1);
lua_register(L, className, create_object);
@@ -584,7 +584,7 @@ void LuaPcgRandom::Register(lua_State *L)
lua_pop(L, 1);
- luaL_openlib(L, 0, methods, 0);
+ luaL_register(L, nullptr, methods);
lua_pop(L, 1);
lua_register(L, className, create_object);
@@ -699,7 +699,7 @@ void LuaSecureRandom::Register(lua_State *L)
lua_pop(L, 1);
- luaL_openlib(L, 0, methods, 0);
+ luaL_register(L, nullptr, methods);
lua_pop(L, 1);
lua_register(L, className, create_object);
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index 8ae99b929..b7185f7ec 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -172,27 +172,11 @@ int ObjectRef::l_punch(lua_State *L)
float time_from_last_punch = readParam<float>(L, 3, 1000000.0f);
ToolCapabilities toolcap = read_tool_capabilities(L, 4);
v3f dir = readParam<v3f>(L, 5, sao->getBasePosition() - puncher->getBasePosition());
-
dir.normalize();
- u16 src_original_hp = sao->getHP();
- u16 dst_origin_hp = puncher->getHP();
u16 wear = sao->punch(dir, &toolcap, puncher, time_from_last_punch);
lua_pushnumber(L, wear);
- // If the punched is a player, and its HP changed
- if (src_original_hp != sao->getHP() &&
- sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
- getServer(L)->SendPlayerHPOrDie((PlayerSAO *)sao,
- PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher));
- }
-
- // If the puncher is a player, and its HP changed
- if (dst_origin_hp != puncher->getHP() &&
- puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
- getServer(L)->SendPlayerHPOrDie((PlayerSAO *)puncher,
- PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, sao));
- }
return 1;
}
@@ -238,8 +222,6 @@ int ObjectRef::l_set_hp(lua_State *L)
}
sao->setHP(hp, reason);
- if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER)
- getServer(L)->SendPlayerHPOrDie((PlayerSAO *)sao, reason);
if (reason.hasLuaReference())
luaL_unref(L, LUA_REGISTRYINDEX, reason.lua_reference);
return 0;
@@ -685,6 +667,7 @@ int ObjectRef::l_set_properties(lua_State *L)
return 0;
read_object_properties(L, 2, sao, prop, getServer(L)->idef());
+ prop->validate();
sao->notifyObjectPropertiesModified();
return 0;
}
@@ -752,6 +735,7 @@ int ObjectRef::l_set_nametag_attributes(lua_State *L)
std::string nametag = getstringfield_default(L, 2, "text", "");
prop->nametag = nametag;
+ prop->validate();
sao->notifyObjectPropertiesModified();
lua_pushboolean(L, true);
return 1;
@@ -1390,13 +1374,13 @@ int ObjectRef::l_get_player_control(lua_State *L)
const PlayerControl &control = player->getPlayerControl();
lua_newtable(L);
- lua_pushboolean(L, control.up);
+ lua_pushboolean(L, player->keyPressed & (1 << 0));
lua_setfield(L, -2, "up");
- lua_pushboolean(L, control.down);
+ lua_pushboolean(L, player->keyPressed & (1 << 1));
lua_setfield(L, -2, "down");
- lua_pushboolean(L, control.left);
+ lua_pushboolean(L, player->keyPressed & (1 << 2));
lua_setfield(L, -2, "left");
- lua_pushboolean(L, control.right);
+ lua_pushboolean(L, player->keyPressed & (1 << 3));
lua_setfield(L, -2, "right");
lua_pushboolean(L, control.jump);
lua_setfield(L, -2, "jump");
@@ -1553,12 +1537,14 @@ int ObjectRef::l_hud_change(lua_State *L)
if (elem == nullptr)
return 0;
+ HudElementStat stat;
void *value = nullptr;
- HudElementStat stat = read_hud_change(L, elem, &value);
+ bool ok = read_hud_change(L, stat, elem, &value);
- getServer(L)->hudChange(player, id, stat, value);
+ if (ok)
+ getServer(L)->hudChange(player, id, stat, value);
- lua_pushboolean(L, true);
+ lua_pushboolean(L, ok);
return 1;
}
@@ -2311,7 +2297,7 @@ void ObjectRef::Register(lua_State *L)
lua_pop(L, 1); // drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // drop methodtable
}
diff --git a/src/script/lua_api/l_playermeta.cpp b/src/script/lua_api/l_playermeta.cpp
index 558672e38..2706c99df 100644
--- a/src/script/lua_api/l_playermeta.cpp
+++ b/src/script/lua_api/l_playermeta.cpp
@@ -97,7 +97,7 @@ void PlayerMetaRef::Register(lua_State *L)
lua_pop(L, 1); // drop metatable
- luaL_openlib(L, 0, methods, 0);
+ luaL_register(L, nullptr, methods);
lua_pop(L, 1);
// Cannot be created from Lua
diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp
index 026f5282c..b4672fe2a 100644
--- a/src/script/lua_api/l_server.cpp
+++ b/src/script/lua_api/l_server.cpp
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_content.h"
#include "cpp_api/s_base.h"
#include "cpp_api/s_security.h"
+#include "scripting_server.h"
#include "server.h"
#include "environment.h"
#include "remoteplayer.h"
@@ -453,29 +454,37 @@ int ModApiServer::l_sound_fade(lua_State *L)
}
// dynamic_add_media(filepath)
-int ModApiServer::l_dynamic_add_media_raw(lua_State *L)
+int ModApiServer::l_dynamic_add_media(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
if (!getEnv(L))
throw LuaError("Dynamic media cannot be added before server has started up");
+ Server *server = getServer(L);
- std::string filepath = readParam<std::string>(L, 1);
- CHECK_SECURE_PATH(L, filepath.c_str(), false);
+ std::string filepath;
+ std::string to_player;
+ bool ephemeral = false;
- std::vector<RemotePlayer*> sent_to;
- bool ok = getServer(L)->dynamicAddMedia(filepath, sent_to);
- if (ok) {
- // (see wrapper code in builtin)
- lua_createtable(L, sent_to.size(), 0);
- int i = 0;
- for (RemotePlayer *player : sent_to) {
- lua_pushstring(L, player->getName());
- lua_rawseti(L, -2, ++i);
- }
+ if (lua_istable(L, 1)) {
+ getstringfield(L, 1, "filepath", filepath);
+ getstringfield(L, 1, "to_player", to_player);
+ getboolfield(L, 1, "ephemeral", ephemeral);
} else {
- lua_pushboolean(L, false);
+ filepath = readParam<std::string>(L, 1);
}
+ if (filepath.empty())
+ luaL_typerror(L, 1, "non-empty string");
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ CHECK_SECURE_PATH(L, filepath.c_str(), false);
+
+ u32 token = server->getScriptIface()->allocateDynamicMediaCallback(2);
+
+ bool ok = server->dynamicAddMedia(filepath, token, to_player, ephemeral);
+ if (!ok)
+ server->getScriptIface()->freeDynamicMediaCallback(token);
+ lua_pushboolean(L, ok);
return 1;
}
@@ -499,31 +508,6 @@ int ModApiServer::l_notify_authentication_modified(lua_State *L)
return 0;
}
-// get_last_run_mod()
-int ModApiServer::l_get_last_run_mod(lua_State *L)
-{
- NO_MAP_LOCK_REQUIRED;
- lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
- 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());
- }
- return 1;
-}
-
-// set_last_run_mod(modname)
-int ModApiServer::l_set_last_run_mod(lua_State *L)
-{
- NO_MAP_LOCK_REQUIRED;
-#ifdef SCRIPTAPI_DEBUG
- const char *mod = lua_tostring(L, 1);
- getScriptApiBase(L)->setOriginDirect(mod);
- //printf(">>>> last mod set from Lua: %s\n", mod);
-#endif
- return 0;
-}
-
void ModApiServer::Initialize(lua_State *L, int top)
{
API_FCT(request_shutdown);
@@ -544,7 +528,7 @@ void ModApiServer::Initialize(lua_State *L, int top)
API_FCT(sound_play);
API_FCT(sound_stop);
API_FCT(sound_fade);
- API_FCT(dynamic_add_media_raw);
+ API_FCT(dynamic_add_media);
API_FCT(get_player_information);
API_FCT(get_player_privs);
@@ -555,7 +539,4 @@ void ModApiServer::Initialize(lua_State *L, int top)
API_FCT(kick_player);
API_FCT(unban_player_or_ip);
API_FCT(notify_authentication_modified);
-
- API_FCT(get_last_run_mod);
- API_FCT(set_last_run_mod);
}
diff --git a/src/script/lua_api/l_server.h b/src/script/lua_api/l_server.h
index 2df180b17..c688e494b 100644
--- a/src/script/lua_api/l_server.h
+++ b/src/script/lua_api/l_server.h
@@ -71,7 +71,7 @@ private:
static int l_sound_fade(lua_State *L);
// dynamic_add_media(filepath)
- static int l_dynamic_add_media_raw(lua_State *L);
+ static int l_dynamic_add_media(lua_State *L);
// get_player_privs(name, text)
static int l_get_player_privs(lua_State *L);
@@ -103,12 +103,6 @@ private:
// notify_authentication_modified(name)
static int l_notify_authentication_modified(lua_State *L);
- // get_last_run_mod()
- static int l_get_last_run_mod(lua_State *L);
-
- // set_last_run_mod(modname)
- static int l_set_last_run_mod(lua_State *L);
-
public:
static void Initialize(lua_State *L, int top);
};
diff --git a/src/script/lua_api/l_settings.cpp b/src/script/lua_api/l_settings.cpp
index a82073ed4..14398dda2 100644
--- a/src/script/lua_api/l_settings.cpp
+++ b/src/script/lua_api/l_settings.cpp
@@ -334,7 +334,7 @@ void LuaSettings::Register(lua_State* L)
lua_pop(L, 1); // drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // drop methodtable
// Can be created from Lua (Settings(filename))
diff --git a/src/script/lua_api/l_storage.cpp b/src/script/lua_api/l_storage.cpp
index cba34fb63..978b315d5 100644
--- a/src/script/lua_api/l_storage.cpp
+++ b/src/script/lua_api/l_storage.cpp
@@ -110,7 +110,7 @@ void StorageRef::Register(lua_State *L)
lua_pop(L, 1); // drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // drop methodtable
}
diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp
index 624828956..d575eb603 100644
--- a/src/script/lua_api/l_util.cpp
+++ b/src/script/lua_api/l_util.cpp
@@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "version.h"
#include "util/hex.h"
#include "util/sha1.h"
+#include "util/png.h"
#include <algorithm>
#include <cstdio>
@@ -271,11 +272,11 @@ int ModApiUtil::l_compress(lua_State *L)
const char *data = luaL_checklstring(L, 1, &size);
int level = -1;
- if (!lua_isnone(L, 3) && !lua_isnil(L, 3))
- level = readParam<float>(L, 3);
+ if (!lua_isnoneornil(L, 3))
+ level = readParam<int>(L, 3);
- std::ostringstream os;
- compressZlib(std::string(data, size), os, level);
+ std::ostringstream os(std::ios_base::binary);
+ compressZlib(reinterpret_cast<const u8 *>(data), size, os, level);
std::string out = os.str();
@@ -291,8 +292,8 @@ int ModApiUtil::l_decompress(lua_State *L)
size_t size;
const char *data = luaL_checklstring(L, 1, &size);
- std::istringstream is(std::string(data, size));
- std::ostringstream os;
+ std::istringstream is(std::string(data, size), std::ios_base::binary);
+ std::ostringstream os(std::ios_base::binary);
decompressZlib(is, os);
std::string out = os.str();
@@ -497,6 +498,67 @@ int ModApiUtil::l_colorspec_to_colorstring(lua_State *L)
return 0;
}
+// colorspec_to_bytes(colorspec)
+int ModApiUtil::l_colorspec_to_bytes(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ video::SColor color(0);
+ if (read_color(L, 1, &color)) {
+ u8 colorbytes[4] = {
+ (u8) color.getRed(),
+ (u8) color.getGreen(),
+ (u8) color.getBlue(),
+ (u8) color.getAlpha(),
+ };
+ lua_pushlstring(L, (const char*) colorbytes, 4);
+ return 1;
+ }
+
+ return 0;
+}
+
+// encode_png(w, h, data, level)
+int ModApiUtil::l_encode_png(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ // The args are already pre-validated on the lua side.
+ u32 width = readParam<int>(L, 1);
+ u32 height = readParam<int>(L, 2);
+ const char *data = luaL_checklstring(L, 3, NULL);
+ s32 compression = readParam<int>(L, 4);
+
+ std::string out = encodePNG((const u8*)data, width, height, compression);
+
+ lua_pushlstring(L, out.data(), out.size());
+ return 1;
+}
+
+// get_last_run_mod()
+int ModApiUtil::l_get_last_run_mod(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
+ 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());
+ }
+ return 1;
+}
+
+// set_last_run_mod(modname)
+int ModApiUtil::l_set_last_run_mod(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ const char *mod = luaL_checkstring(L, 1);
+ getScriptApiBase(L)->setOriginDirect(mod);
+ return 0;
+}
+
void ModApiUtil::Initialize(lua_State *L, int top)
{
API_FCT(log);
@@ -532,6 +594,12 @@ void ModApiUtil::Initialize(lua_State *L, int top)
API_FCT(get_version);
API_FCT(sha1);
API_FCT(colorspec_to_colorstring);
+ API_FCT(colorspec_to_bytes);
+
+ API_FCT(encode_png);
+
+ API_FCT(get_last_run_mod);
+ API_FCT(set_last_run_mod);
LuaSettings::create(L, g_settings, g_settings_path);
lua_setfield(L, top, "settings");
@@ -559,6 +627,7 @@ void ModApiUtil::InitializeClient(lua_State *L, int top)
API_FCT(get_version);
API_FCT(sha1);
API_FCT(colorspec_to_colorstring);
+ API_FCT(colorspec_to_bytes);
LuaSettings::create(L, g_settings, g_settings_path);
lua_setfield(L, top, "settings");
@@ -590,6 +659,10 @@ void ModApiUtil::InitializeAsync(lua_State *L, int top)
API_FCT(get_version);
API_FCT(sha1);
API_FCT(colorspec_to_colorstring);
+ API_FCT(colorspec_to_bytes);
+
+ API_FCT(get_last_run_mod);
+ API_FCT(set_last_run_mod);
LuaSettings::create(L, g_settings, g_settings_path);
lua_setfield(L, top, "settings");
diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h
index 6943a6afb..cc91e8d39 100644
--- a/src/script/lua_api/l_util.h
+++ b/src/script/lua_api/l_util.h
@@ -104,6 +104,18 @@ private:
// colorspec_to_colorstring(colorspec)
static int l_colorspec_to_colorstring(lua_State *L);
+ // colorspec_to_bytes(colorspec)
+ static int l_colorspec_to_bytes(lua_State *L);
+
+ // encode_png(w, h, data, level)
+ static int l_encode_png(lua_State *L);
+
+ // get_last_run_mod()
+ static int l_get_last_run_mod(lua_State *L);
+
+ // set_last_run_mod(modname)
+ static int l_set_last_run_mod(lua_State *L);
+
public:
static void Initialize(lua_State *L, int top);
static void InitializeAsync(lua_State *L, int top);
diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp
index b99b1d98c..e040e545b 100644
--- a/src/script/lua_api/l_vmanip.cpp
+++ b/src/script/lua_api/l_vmanip.cpp
@@ -450,7 +450,7 @@ void LuaVoxelManip::Register(lua_State *L)
lua_pop(L, 1); // drop metatable
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+ luaL_register(L, nullptr, methods); // fill methodtable
lua_pop(L, 1); // drop methodtable
// Can be created from Lua (VoxelManip())
diff --git a/src/script/scripting_mainmenu.cpp b/src/script/scripting_mainmenu.cpp
index b102a66a1..2a0cadb23 100644
--- a/src/script/scripting_mainmenu.cpp
+++ b/src/script/scripting_mainmenu.cpp
@@ -92,9 +92,9 @@ void MainMenuScripting::step()
}
/******************************************************************************/
-unsigned int MainMenuScripting::queueAsync(const std::string &serialized_func,
- const std::string &serialized_param)
+u32 MainMenuScripting::queueAsync(std::string &&serialized_func,
+ std::string &&serialized_param)
{
- return asyncEngine.queueAsyncJob(serialized_func, serialized_param);
+ return asyncEngine.queueAsyncJob(std::move(serialized_func), std::move(serialized_param));
}
diff --git a/src/script/scripting_mainmenu.h b/src/script/scripting_mainmenu.h
index 9e23bdc1b..3c329654a 100644
--- a/src/script/scripting_mainmenu.h
+++ b/src/script/scripting_mainmenu.h
@@ -38,8 +38,9 @@ public:
void step();
// Pass async events from engine to async threads
- unsigned int queueAsync(const std::string &serialized_func,
- const std::string &serialized_params);
+ u32 queueAsync(std::string &&serialized_func,
+ std::string &&serialized_param);
+
private:
void initializeModApi(lua_State *L, int top);
static void registerLuaClasses(lua_State *L, int top);