#include "common/c_converter.h"
#include "log.h"
#include "environment.h"
-#include "mapgen.h"
+#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)
lua_getfield(L, -1, "registered_globalsteps");
// Call callbacks
lua_pushnumber(L, dtime);
- try {
- runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
- } catch (LuaError &e) {
- getServer()->setAsyncFatalError(e.what());
- }
+ runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
}
void ScriptApiEnv::player_event(ServerActiveObject *player, const std::string &type)
// 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(e.what());
- }
+ runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
}
void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env)
{
SCRIPTAPI_PRECHECKHEADER
- verbosestream << "scriptapi_add_environment" << std::endl;
+ verbosestream << "ScriptApiEnv: Environment initialized" << std::endl;
setEnv(env);
/*
int id = lua_tonumber(L, -2);
int current_abm = lua_gettop(L);
- std::set<std::string> trigger_contents;
+ std::vector<std::string> trigger_contents;
lua_getfield(L, current_abm, "nodenames");
if (lua_istable(L, -1)) {
int table = lua_gettop(L);
while (lua_next(L, table)) {
// key at index -2 and value at index -1
luaL_checktype(L, -1, LUA_TSTRING);
- trigger_contents.insert(lua_tostring(L, -1));
+ trigger_contents.emplace_back(readParam<std::string>(L, -1));
// removes value, keeps key for next iteration
lua_pop(L, 1);
}
} else if (lua_isstring(L, -1)) {
- trigger_contents.insert(lua_tostring(L, -1));
+ trigger_contents.emplace_back(readParam<std::string>(L, -1));
}
lua_pop(L, 1);
- std::set<std::string> required_neighbors;
+ std::vector<std::string> required_neighbors;
lua_getfield(L, current_abm, "neighbors");
if (lua_istable(L, -1)) {
int table = lua_gettop(L);
while (lua_next(L, table)) {
// key at index -2 and value at index -1
luaL_checktype(L, -1, LUA_TSTRING);
- required_neighbors.insert(lua_tostring(L, -1));
+ required_neighbors.emplace_back(readParam<std::string>(L, -1));
// removes value, keeps key for next iteration
lua_pop(L, 1);
}
} else if (lua_isstring(L, -1)) {
- required_neighbors.insert(lua_tostring(L, -1));
+ required_neighbors.emplace_back(readParam<std::string>(L, -1));
}
lua_pop(L, 1);
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);
while (lua_next(L, table)) {
// key at index -2 and value at index -1
luaL_checktype(L, -1, LUA_TSTRING);
- trigger_contents.insert(lua_tostring(L, -1));
+ trigger_contents.insert(readParam<std::string>(L, -1));
// removes value, keeps key for next iteration
lua_pop(L, 1);
}
} else if (lua_isstring(L, -1)) {
- trigger_contents.insert(lua_tostring(L, -1));
+ trigger_contents.insert(readParam<std::string>(L, -1));
}
lua_pop(L, 1);
bool run_at_every_load = getboolfield_default(L, current_lbm,
"run_at_every_load", false);
+ lua_getfield(L, current_lbm, "action");
+ luaL_checktype(L, current_lbm + 1, LUA_TFUNCTION);
+ lua_pop(L, 1);
+
LuaLBM *lbm = new LuaLBM(L, id, trigger_contents, name,
run_at_every_load);
{
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
try {
PCALL_RES(lua_pcall(L, 4, 0, error_handler));
} catch (LuaError &e) {
- server->setAsyncFatalError(e.what());
+ // Note: don't throw here, we still need to run the cleanup code below
+ server->setAsyncFatalError(e);
}
lua_pop(L, 1); // Pop error handler
luaL_unref(L, LUA_REGISTRYINDEX, state->args_ref);
}
}
+
+void ScriptApiEnv::check_for_falling(v3s16 p)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ int error_handler = PUSH_ERROR_HANDLER(L);
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "check_for_falling");
+ luaL_checktype(L, -1, LUA_TFUNCTION);
+ push_v3s16(L, p);
+ PCALL_RES(lua_pcall(L, 1, 0, error_handler));
+}
+
+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;
+ 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);
+ lua_rawset(L, -3);
+ }
+
+ runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
+}
+
+void ScriptApiEnv::on_mapblocks_changed(const std::unordered_set<v3s16> &set)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_mapblocks_changed
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_mapblocks_changed");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ lua_remove(L, -2);
+
+ // Convert the set to a set of position hashes
+ lua_createtable(L, 0, set.size());
+ for(const v3s16 &p : set) {
+ lua_pushnumber(L, hash_node_position(p));
+ lua_pushboolean(L, true);
+ lua_rawset(L, -3);
+ }
+ lua_pushinteger(L, set.size());
+
+ runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
+}
+
+bool ScriptApiEnv::has_on_mapblocks_changed()
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_mapblocks_changed
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_mapblocks_changed");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ return lua_objlen(L, -1) > 0;
+}