// Return number of accepted items to be moved int ScriptApiDetached::detached_inventory_AllowMove( const std::string &name, const std::string &from_list, int from_index, const std::string &to_list, int to_index, int count, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getDetachedInventoryCallback(name, "allow_move")) return count; // function(inv, from_list, from_index, to_list, to_index, count, player) // inv InventoryLocation loc; loc.setDetached(name); InvRef::create(L, loc); lua_pushstring(L, from_list.c_str()); // from_list lua_pushinteger(L, from_index + 1); // from_index lua_pushstring(L, to_list.c_str()); // to_list lua_pushinteger(L, to_index + 1); // to_index lua_pushinteger(L, count); // count objectrefGetOrCreate(L, player); // player PCALL_RES(lua_pcall(L, 7, 1, error_handler)); if(!lua_isnumber(L, -1)) throw LuaError("allow_move should return a number. name=" + name); int ret = luaL_checkinteger(L, -1); lua_pop(L, 2); // Pop integer and error handler return ret; }
// Report taken items void ScriptApiDetached::detached_inventory_OnTake( const std::string &name, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getDetachedInventoryCallback(name, "on_take")) return; // Call function(inv, listname, index, stack, player) // inv InventoryLocation loc; loc.setDetached(name); InvRef::create(L, loc); lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(L, player); // player PCALL_RES(lua_pcall(L, 5, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
// Report moved items void ScriptApiDetached::detached_inventory_OnMove( const std::string &name, const std::string &from_list, int from_index, const std::string &to_list, int to_index, int count, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getDetachedInventoryCallback(name, "on_move")) return; // function(inv, from_list, from_index, to_list, to_index, count, player) // inv InventoryLocation loc; loc.setDetached(name); InvRef::create(L, loc); lua_pushstring(L, from_list.c_str()); // from_list lua_pushinteger(L, from_index + 1); // from_index lua_pushstring(L, to_list.c_str()); // to_list lua_pushinteger(L, to_index + 1); // to_index lua_pushinteger(L, count); // count objectrefGetOrCreate(L, player); // player PCALL_RES(lua_pcall(L, 7, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
// Return number of accepted items to be put int ScriptApiNodemeta::nodemeta_inventory_AllowPut(v3s16 p, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if (node.getContent() == CONTENT_IGNORE) return 0; // Push callback function on stack std::string nodename = ndef->get(node).name; if (!getItemCallback(nodename.c_str(), "allow_metadata_inventory_put", &p)) return stack.count; // Call function(pos, listname, index, stack, player) push_v3s16(L, p); // pos lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(L, player); // player 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); int num = luaL_checkinteger(L, -1); lua_pop(L, 2); // Pop integer and error handler return num; }
// Return number of accepted items to be taken int ScriptApiDetached::detached_inventory_AllowTake( const std::string &name, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getDetachedInventoryCallback(name, "allow_take")) return stack.count; // All will be accepted // Call function(inv, listname, index, stack, player) InventoryLocation loc; loc.setDetached(name); InvRef::create(L, loc); // inv lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(L, player); // player PCALL_RES(lua_pcall(L, 5, 1, error_handler)); if (!lua_isnumber(L, -1)) throw LuaError("allow_take should return a number. name=" + name); int ret = luaL_checkinteger(L, -1); lua_pop(L, 2); // Pop integer and error handler return ret; }
bool ScriptApiItem::item_OnUse(ItemStack &item, ServerActiveObject *user, const PointedThing &pointed) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getItemCallback(item.name.c_str(), "on_use")) return false; // Call function LuaItemStack::create(L, item); objectrefGetOrCreate(L, user); pushPointedThing(pointed); PCALL_RES(lua_pcall(L, 3, 1, error_handler)); if(!lua_isnil(L, -1)) { try { item = read_item(L,-1, getServer()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } } lua_pop(L, 2); // Pop item and error handler return true; }
// Report moved items void ScriptApiNodemeta::nodemeta_inventory_OnMove(v3s16 p, const std::string &from_list, int from_index, const std::string &to_list, int to_index, int count, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if (node.getContent() == CONTENT_IGNORE) return; // Push callback function on stack std::string nodename = ndef->get(node).name; if (!getItemCallback(nodename.c_str(), "on_metadata_inventory_move", &p)) return; // function(pos, from_list, from_index, to_list, to_index, count, player) push_v3s16(L, p); // pos lua_pushstring(L, from_list.c_str()); // from_list lua_pushinteger(L, from_index + 1); // from_index lua_pushstring(L, to_list.c_str()); // to_list lua_pushinteger(L, to_index + 1); // to_index lua_pushinteger(L, count); // count objectrefGetOrCreate(L, player); // player PCALL_RES(lua_pcall(L, 7, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
bool ScriptApiEntity::luaentity_on_death(u16 id, ServerActiveObject *killer) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Get core.luaentities[id] luaentity_get(L, id); int object = lua_gettop(L); // State: object is at top of stack // Get function lua_getfield(L, -1, "on_death"); if (lua_isnil(L, -1)) { lua_pop(L, 2); // Pop on_death and entity return false; } luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self objectrefGetOrCreate(L, killer); // killer reference setOriginFromTable(object); PCALL_RES(lua_pcall(L, 2, 1, error_handler)); bool retval = lua_toboolean(L, -1); lua_pop(L, 2); // Pop object and error handler return retval; }
void ScriptApiEntity::luaentity_Step(u16 id, float dtime) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl; int error_handler = PUSH_ERROR_HANDLER(L); // Get core.luaentities[id] luaentity_get(L, id); int object = lua_gettop(L); // State: object is at top of stack // Get step function lua_getfield(L, -1, "on_step"); if (lua_isnil(L, -1)) { lua_pop(L, 2); // Pop on_step and entity return; } luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self lua_pushnumber(L, dtime); // dtime setOriginFromTable(object); PCALL_RES(lua_pcall(L, 2, 0, error_handler)); lua_pop(L, 2); // Pop object and error handler }
// Calls entity:on_rightclick(ObjectRef clicker) void ScriptApiEntity::luaentity_Rightclick(u16 id, ServerActiveObject *clicker) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl; int error_handler = PUSH_ERROR_HANDLER(L); // Get core.luaentities[id] luaentity_get(L, id); int object = lua_gettop(L); // State: object is at top of stack // Get function lua_getfield(L, -1, "on_rightclick"); if (lua_isnil(L, -1)) { lua_pop(L, 2); // Pop on_rightclick and entity return; } luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self objectrefGetOrCreate(L, clicker); // Clicker reference setOriginFromTable(object); PCALL_RES(lua_pcall(L, 2, 0, error_handler)); lua_pop(L, 2); // Pop object and error handler }
void ScriptApiEntity::luaentity_Activate(u16 id, const std::string &staticdata, u32 dtime_s) { SCRIPTAPI_PRECHECKHEADER verbosestream << "scriptapi_luaentity_activate: id=" << id << std::endl; int error_handler = PUSH_ERROR_HANDLER(L); // Get core.luaentities[id] luaentity_get(L, id); int object = lua_gettop(L); // Get on_activate function lua_getfield(L, -1, "on_activate"); if (!lua_isnil(L, -1)) { luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self lua_pushlstring(L, staticdata.c_str(), staticdata.size()); lua_pushinteger(L, dtime_s); setOriginFromTable(object); PCALL_RES(lua_pcall(L, 3, 0, error_handler)); } else { lua_pop(L, 1); } lua_pop(L, 2); // Pop object and error handler }
// Report taken items void ScriptApiNodemeta::nodemeta_inventory_OnTake(v3s16 p, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if (node.getContent() == CONTENT_IGNORE) return; // Push callback function on stack std::string nodename = ndef->get(node).name; if (!getItemCallback(nodename.c_str(), "on_metadata_inventory_take", &p)) return; // Call function(pos, listname, index, stack, player) push_v3s16(L, p); // pos lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(L, player); // player PCALL_RES(lua_pcall(L, 5, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
void ScriptApiMainMenu::handleMainMenuButtons(const StringMap &fields) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Get handler function lua_getglobal(L, "core"); lua_getfield(L, -1, "button_handler"); lua_remove(L, -2); // Remove core if (lua_isnil(L, -1)) { lua_pop(L, 1); // Pop button handler return; } luaL_checktype(L, -1, LUA_TFUNCTION); // Convert fields to a Lua table lua_newtable(L); StringMap::const_iterator it; for (it = fields.begin(); it != fields.end(); ++it) { const std::string &name = it->first; const std::string &value = it->second; lua_pushstring(L, name.c_str()); lua_pushlstring(L, value.c_str(), value.size()); lua_settable(L, -3); } // Call it PCALL_RES(lua_pcall(L, 1, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user, const InventoryList *old_craft_grid, const InventoryLocation &craft_inv) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); lua_getglobal(L, "core"); lua_getfield(L, -1, "craft_predict"); LuaItemStack::create(L, item); objectrefGetOrCreate(L, user); //Push inventory list std::vector<ItemStack> items; for (u32 i = 0; i < old_craft_grid->getSize(); i++) { items.push_back(old_craft_grid->getItem(i)); } push_items(L, items); InvRef::create(L, craft_inv); PCALL_RES(lua_pcall(L, 4, 1, error_handler)); if (!lua_isnil(L, -1)) { try { item = read_item(L,-1, getServer()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } } lua_pop(L, 2); // Pop item and error handler return true; }
// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch, // tool_capabilities, direction, damage) bool ScriptApiEntity::luaentity_Punch(u16 id, ServerActiveObject *puncher, float time_from_last_punch, const ToolCapabilities *toolcap, v3f dir, s16 damage) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl; int error_handler = PUSH_ERROR_HANDLER(L); // Get core.luaentities[id] luaentity_get(L,id); int object = lua_gettop(L); // State: object is at top of stack // Get function lua_getfield(L, -1, "on_punch"); if (lua_isnil(L, -1)) { lua_pop(L, 2); // Pop on_punch and entity return false; } luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self objectrefGetOrCreate(L, puncher); // Clicker reference lua_pushnumber(L, time_from_last_punch); push_tool_capabilities(L, *toolcap); push_v3f(L, dir); lua_pushnumber(L, damage); setOriginFromTable(object); PCALL_RES(lua_pcall(L, 6, 1, error_handler)); bool retval = lua_toboolean(L, -1); lua_pop(L, 2); // Pop object and error handler return retval; }
std::string ScriptApiEntity::luaentity_GetStaticdata(u16 id) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl; int error_handler = PUSH_ERROR_HANDLER(L); // Get core.luaentities[id] luaentity_get(L, id); int object = lua_gettop(L); // Get get_staticdata function lua_getfield(L, -1, "get_staticdata"); if (lua_isnil(L, -1)) { lua_pop(L, 2); // Pop entity and get_staticdata return ""; } luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self setOriginFromTable(object); PCALL_RES(lua_pcall(L, 1, 1, error_handler)); lua_remove(L, object); lua_remove(L, error_handler); size_t len = 0; const char *s = lua_tolstring(L, -1, &len); lua_pop(L, 1); // Pop static data return std::string(s, len); }
void ScriptApiNode::node_falling_update_single(v3s16 p) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); lua_getglobal(L, "nodeupdate_single"); push_v3s16(L, p); PCALL_RES(lua_pcall(L, 1, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
void ScriptApiNode::node_drop(v3s16 p, int fast = 0) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); lua_getglobal(L, "node_drop"); push_v3s16(L, p); lua_pushinteger(L, fast); PCALL_RES(lua_pcall(L, 2, 0, errorhandler)); lua_pop(L, 1); // Pop error handler }
void ScriptApiServer::createAuth(const std::string &playername, const std::string &password) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); getAuthHandler(); lua_getfield(L, -1, "create_auth"); lua_remove(L, -2); // Remove auth handler if (lua_type(L, -1) != LUA_TFUNCTION) throw LuaError("Authentication handler missing create_auth"); lua_pushstring(L, playername.c_str()); lua_pushstring(L, password.c_str()); PCALL_RES(lua_pcall(L, 2, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
void ScriptApiNode::node_on_destruct(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "on_destruct")) return; // Call function push_v3s16(L, p); PCALL_RES(lua_pcall(L, 1, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
bool ScriptApiServer::setPassword(const std::string &playername, const std::string &password) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); getAuthHandler(); lua_getfield(L, -1, "set_password"); lua_remove(L, -2); // Remove auth handler if (lua_type(L, -1) != LUA_TFUNCTION) throw LuaError("Authentication handler missing set_password"); lua_pushstring(L, playername.c_str()); lua_pushstring(L, password.c_str()); PCALL_RES(lua_pcall(L, 2, 1, error_handler)); lua_remove(L, error_handler); return lua_toboolean(L, -1); }
void ScriptApiNode::node_on_deactivate(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if(!getItemCallback(ndef->get(node).name.c_str(), "on_deactivate")) return; // Call function push_v3s16(L, p); PCALL_RES(lua_pcall(L, 1, 0, errorhandler)); lua_pop(L, 1); // Pop error handler }
s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player, s16 hp_change) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Get core.registered_on_player_hpchange lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_player_hpchange"); lua_remove(L, -2); objectrefGetOrCreate(L, player); lua_pushnumber(L, hp_change); PCALL_RES(lua_pcall(L, 2, 1, error_handler)); hp_change = lua_tointeger(L, -1); lua_pop(L, 2); // Pop result and error handler return hp_change; }
bool ScriptApiNode::node_on_timer(v3s16 p, MapNode node, f32 dtime) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "on_timer")) return false; // Call function push_v3s16(L, p); lua_pushnumber(L,dtime); PCALL_RES(lua_pcall(L, 2, 1, error_handler)); lua_remove(L, error_handler); return (bool) lua_isboolean(L, -1) && (bool) lua_toboolean(L, -1) == true; }
void ScriptApiMainMenu::handleMainMenuEvent(std::string text) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Get handler function lua_getglobal(L, "core"); lua_getfield(L, -1, "event_handler"); lua_remove(L, -2); // Remove core if (lua_isnil(L, -1)) { lua_pop(L, 1); // Pop event_handler return; } luaL_checktype(L, -1, LUA_TFUNCTION); // Call it lua_pushstring(L, text.c_str()); PCALL_RES(lua_pcall(L, 1, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
bool ScriptApiNode::node_on_dig(v3s16 p, MapNode node, ServerActiveObject *digger) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "on_dig")) return false; // Call function push_v3s16(L, p); pushnode(L, node, ndef); objectrefGetOrCreate(L, digger); PCALL_RES(lua_pcall(L, 3, 0, error_handler)); lua_pop(L, 1); // Pop error handler return true; }
bool ScriptApiServer::getAuth(const std::string &playername, std::string *dst_password, std::set<std::string> *dst_privs) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); getAuthHandler(); lua_getfield(L, -1, "get_auth"); if (lua_type(L, -1) != LUA_TFUNCTION) throw LuaError("Authentication handler missing get_auth"); lua_pushstring(L, playername.c_str()); PCALL_RES(lua_pcall(L, 1, 1, error_handler)); lua_remove(L, -2); // Remove auth handler lua_remove(L, error_handler); // nil = login not allowed if (lua_isnil(L, -1)) return false; luaL_checktype(L, -1, LUA_TTABLE); std::string password; bool found = getstringfield(L, -1, "password", password); if (!found) throw LuaError("Authentication handler didn't return password"); if (dst_password) *dst_password = password; lua_getfield(L, -1, "privileges"); if (!lua_istable(L, -1)) throw LuaError("Authentication handler didn't return privilege table"); if (dst_privs) readPrivileges(-1, *dst_privs); lua_pop(L, 1); return true; }
void ScriptApiNode::node_on_receive_fields(v3s16 p, const std::string &formname, const StringMap &fields, ServerActiveObject *sender) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if (node.getContent() == CONTENT_IGNORE) return; // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "on_receive_fields")) return; // Call function push_v3s16(L, p); // pos lua_pushstring(L, formname.c_str()); // formname lua_newtable(L); // fields StringMap::const_iterator it; for (it = fields.begin(); it != fields.end(); it++) { const std::string &name = it->first; const std::string &value = it->second; lua_pushstring(L, name.c_str()); lua_pushlstring(L, value.c_str(), value.size()); lua_settable(L, -3); } objectrefGetOrCreate(L, sender); // player PCALL_RES(lua_pcall(L, 4, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
void* AsyncWorkerThread::run() { lua_State *L = getStack(); std::string script = getServer()->getBuiltinLuaPath() + DIR_DELIM + "init.lua"; try { loadScript(script); } catch (const ModError &e) { errorstream << "Execution of async base environment failed: " << e.what() << std::endl; FATAL_ERROR("Execution of async base environment failed"); } int error_handler = PUSH_ERROR_HANDLER(L); lua_getglobal(L, "core"); if (lua_isnil(L, -1)) { FATAL_ERROR("Unable to find core within async environment!"); } // Main loop while (!stopRequested()) { // Wait for job LuaJobInfo toProcess = jobDispatcher->getJob(); if (!toProcess.valid || stopRequested()) { continue; } lua_getfield(L, -1, "job_processor"); 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()); int result = lua_pcall(L, 2, 1, error_handler); if (result) { PCALL_RES(result); toProcess.serializedResult = ""; } else { // Fetch result size_t length; const char *retval = lua_tolstring(L, -1, &length); toProcess.serializedResult = std::string(retval, length); } lua_pop(L, 1); // Pop retval // Put job result jobDispatcher->putJobResult(toProcess); } lua_pop(L, 2); // Pop core and error handler return 0; }
void* AsyncWorkerThread::Thread() { ThreadStarted(); // Register thread for error logging char number[21]; snprintf(number, sizeof(number), "%u", threadnum); log_register_thread(std::string("AsyncWorkerThread_") + number); porting::setThreadName((std::string("AsyncWorkTh_") + number).c_str()); lua_State *L = getStack(); std::string script = getServer()->getBuiltinLuaPath() + DIR_DELIM + "init.lua"; if (!loadScript(script)) { errorstream << "AsyncWorkerThread execution of async base environment failed!" << std::endl; abort(); } lua_getglobal(L, "core"); if (lua_isnil(L, -1)) { errorstream << "Unable to find core within async environment!"; abort(); } // Main loop while (!StopRequested()) { // Wait for job LuaJobInfo toProcess = jobDispatcher->getJob(); if (toProcess.valid == false || StopRequested()) { continue; } lua_getfield(L, -1, "job_processor"); if (lua_isnil(L, -1)) { errorstream << "Unable to get async job processor!" << std::endl; abort(); } 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()); int result = lua_pcall(L, 2, 1, m_errorhandler); if (result) { PCALL_RES(result); toProcess.serializedResult = ""; } else { // Fetch result size_t length; const char *retval = lua_tolstring(L, -1, &length); toProcess.serializedResult = std::string(retval, length); } lua_pop(L, 1); // Pop retval // Put job result jobDispatcher->putJobResult(toProcess); } lua_pop(L, 1); // Pop core log_deregister_thread(); return 0; }