s_base.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "cpp_api/s_base.h"
  17. #include "cpp_api/s_internal.h"
  18. #include "cpp_api/s_security.h"
  19. #include "lua_api/l_object.h"
  20. #include "common/c_converter.h"
  21. #include "server/player_sao.h"
  22. #include "filesys.h"
  23. #include "content/mods.h"
  24. #include "porting.h"
  25. #include "util/string.h"
  26. #include "server.h"
  27. #ifndef SERVER
  28. #include "client/client.h"
  29. #endif
  30. extern "C" {
  31. #include "lualib.h"
  32. #if USE_LUAJIT
  33. #include "luajit.h"
  34. #else
  35. #include "bit.h"
  36. #endif
  37. }
  38. #include <cstdio>
  39. #include <cstdarg>
  40. #include "script/common/c_content.h"
  41. #include <sstream>
  42. class ModNameStorer
  43. {
  44. private:
  45. lua_State *L;
  46. public:
  47. ModNameStorer(lua_State *L_, const std::string &mod_name):
  48. L(L_)
  49. {
  50. // Store current mod name in registry
  51. lua_pushstring(L, mod_name.c_str());
  52. lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
  53. }
  54. ~ModNameStorer()
  55. {
  56. // Clear current mod name from registry
  57. lua_pushnil(L);
  58. lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
  59. }
  60. };
  61. /*
  62. ScriptApiBase
  63. */
  64. ScriptApiBase::ScriptApiBase(ScriptingType type):
  65. m_type(type)
  66. {
  67. #ifdef SCRIPTAPI_LOCK_DEBUG
  68. m_lock_recursion_count = 0;
  69. #endif
  70. m_luastack = luaL_newstate();
  71. FATAL_ERROR_IF(!m_luastack, "luaL_newstate() failed");
  72. lua_atpanic(m_luastack, &luaPanic);
  73. if (m_type == ScriptingType::Client)
  74. clientOpenLibs(m_luastack);
  75. else
  76. luaL_openlibs(m_luastack);
  77. // Load bit library
  78. lua_pushcfunction(m_luastack, luaopen_bit);
  79. lua_pushstring(m_luastack, LUA_BITLIBNAME);
  80. lua_call(m_luastack, 1, 0);
  81. // Make the ScriptApiBase* accessible to ModApiBase
  82. #if INDIRECT_SCRIPTAPI_RIDX
  83. *(void **)(lua_newuserdata(m_luastack, sizeof(void *))) = this;
  84. #else
  85. lua_pushlightuserdata(m_luastack, this);
  86. #endif
  87. lua_rawseti(m_luastack, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
  88. lua_pushcfunction(m_luastack, script_error_handler);
  89. lua_rawseti(m_luastack, LUA_REGISTRYINDEX, CUSTOM_RIDX_ERROR_HANDLER);
  90. // Add a C++ wrapper function to catch exceptions thrown in Lua -> C++ calls
  91. #if USE_LUAJIT
  92. lua_pushlightuserdata(m_luastack, (void*) script_exception_wrapper);
  93. luaJIT_setmode(m_luastack, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
  94. lua_pop(m_luastack, 1);
  95. #else
  96. // (This is a custom API from the bundled Lua.)
  97. lua_atccall(m_luastack, script_exception_wrapper);
  98. #endif
  99. // Add basic globals
  100. // "core" table:
  101. lua_newtable(m_luastack);
  102. // Populate with some internal functions which will be removed in Lua:
  103. lua_pushcfunction(m_luastack, [](lua_State *L) -> int {
  104. lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_READ_VECTOR);
  105. return 0;
  106. });
  107. lua_setfield(m_luastack, -2, "set_read_vector");
  108. lua_pushcfunction(m_luastack, [](lua_State *L) -> int {
  109. lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_PUSH_VECTOR);
  110. return 0;
  111. });
  112. lua_setfield(m_luastack, -2, "set_push_vector");
  113. lua_pushcfunction(m_luastack, [](lua_State *L) -> int {
  114. lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_READ_NODE);
  115. return 0;
  116. });
  117. lua_setfield(m_luastack, -2, "set_read_node");
  118. lua_pushcfunction(m_luastack, [](lua_State *L) -> int {
  119. lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_PUSH_NODE);
  120. return 0;
  121. });
  122. lua_setfield(m_luastack, -2, "set_push_node");
  123. // Finally, put the table into the global environment:
  124. lua_setglobal(m_luastack, "core");
  125. if (m_type == ScriptingType::Client)
  126. lua_pushstring(m_luastack, "/");
  127. else
  128. lua_pushstring(m_luastack, DIR_DELIM);
  129. lua_setglobal(m_luastack, "DIR_DELIM");
  130. lua_pushstring(m_luastack, porting::getPlatformName());
  131. lua_setglobal(m_luastack, "PLATFORM");
  132. // Make sure Lua uses the right locale
  133. setlocale(LC_NUMERIC, "C");
  134. }
  135. ScriptApiBase::~ScriptApiBase()
  136. {
  137. lua_close(m_luastack);
  138. }
  139. int ScriptApiBase::luaPanic(lua_State *L)
  140. {
  141. std::ostringstream oss;
  142. oss << "LUA PANIC: unprotected error in call to Lua API ("
  143. << readParam<std::string>(L, -1) << ")";
  144. FATAL_ERROR(oss.str().c_str());
  145. // NOTREACHED
  146. return 0;
  147. }
  148. void ScriptApiBase::clientOpenLibs(lua_State *L)
  149. {
  150. static const std::vector<std::pair<std::string, lua_CFunction>> m_libs = {
  151. { "", luaopen_base },
  152. { LUA_TABLIBNAME, luaopen_table },
  153. { LUA_OSLIBNAME, luaopen_os },
  154. { LUA_STRLIBNAME, luaopen_string },
  155. { LUA_MATHLIBNAME, luaopen_math },
  156. { LUA_DBLIBNAME, luaopen_debug },
  157. #if USE_LUAJIT
  158. { LUA_JITLIBNAME, luaopen_jit },
  159. #endif
  160. };
  161. for (const auto &lib : m_libs) {
  162. lua_pushcfunction(L, lib.second);
  163. lua_pushstring(L, lib.first.c_str());
  164. lua_call(L, 1, 0);
  165. }
  166. }
  167. void ScriptApiBase::checkSetByBuiltin()
  168. {
  169. lua_State *L = getStack();
  170. if (m_gamedef) {
  171. lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_READ_VECTOR);
  172. FATAL_ERROR_IF(lua_type(L, -1) != LUA_TFUNCTION, "missing read_vector");
  173. lua_pop(L, 1);
  174. lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_PUSH_VECTOR);
  175. FATAL_ERROR_IF(lua_type(L, -1) != LUA_TFUNCTION, "missing push_vector");
  176. lua_pop(L, 1);
  177. lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_READ_NODE);
  178. FATAL_ERROR_IF(lua_type(L, -1) != LUA_TFUNCTION, "missing read_node");
  179. lua_pop(L, 1);
  180. lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_PUSH_NODE);
  181. FATAL_ERROR_IF(lua_type(L, -1) != LUA_TFUNCTION, "missing push_node");
  182. lua_pop(L, 1);
  183. }
  184. }
  185. void ScriptApiBase::loadMod(const std::string &script_path,
  186. const std::string &mod_name)
  187. {
  188. ModNameStorer mod_name_storer(getStack(), mod_name);
  189. loadScript(script_path);
  190. }
  191. void ScriptApiBase::loadScript(const std::string &script_path)
  192. {
  193. verbosestream << "Loading and running script from " << script_path << std::endl;
  194. lua_State *L = getStack();
  195. int error_handler = PUSH_ERROR_HANDLER(L);
  196. bool ok;
  197. if (m_secure) {
  198. ok = ScriptApiSecurity::safeLoadFile(L, script_path.c_str());
  199. } else {
  200. ok = !luaL_loadfile(L, script_path.c_str());
  201. }
  202. ok = ok && !lua_pcall(L, 0, 0, error_handler);
  203. if (!ok) {
  204. const char *error_msg = lua_tostring(L, -1);
  205. if (!error_msg)
  206. error_msg = "(error object is not a string)";
  207. lua_pop(L, 2); // Pop error message and error handler
  208. throw ModError("Failed to load and run script from " +
  209. script_path + ":\n" + error_msg);
  210. }
  211. lua_pop(L, 1); // Pop error handler
  212. }
  213. #ifndef SERVER
  214. void ScriptApiBase::loadModFromMemory(const std::string &mod_name)
  215. {
  216. ModNameStorer mod_name_storer(getStack(), mod_name);
  217. sanity_check(m_type == ScriptingType::Client);
  218. const std::string init_filename = mod_name + ":init.lua";
  219. const std::string chunk_name = "@" + init_filename;
  220. const std::string *contents = getClient()->getModFile(init_filename);
  221. if (!contents)
  222. throw ModError("Mod \"" + mod_name + "\" lacks init.lua");
  223. verbosestream << "Loading and running script " << chunk_name << std::endl;
  224. lua_State *L = getStack();
  225. int error_handler = PUSH_ERROR_HANDLER(L);
  226. bool ok = ScriptApiSecurity::safeLoadString(L, *contents, chunk_name.c_str());
  227. if (ok)
  228. ok = !lua_pcall(L, 0, 0, error_handler);
  229. if (!ok) {
  230. const char *error_msg = lua_tostring(L, -1);
  231. if (!error_msg)
  232. error_msg = "(error object is not a string)";
  233. lua_pop(L, 2); // Pop error message and error handler
  234. throw ModError("Failed to load and run mod \"" +
  235. mod_name + "\":\n" + error_msg);
  236. }
  237. lua_pop(L, 1); // Pop error handler
  238. }
  239. #endif
  240. // Push the list of callbacks (a lua table).
  241. // Then push nargs arguments.
  242. // Then call this function, which
  243. // - runs the callbacks
  244. // - replaces the table and arguments with the return value,
  245. // computed depending on mode
  246. // This function must only be called with scriptlock held (i.e. inside of a
  247. // code block with SCRIPTAPI_PRECHECKHEADER declared)
  248. void ScriptApiBase::runCallbacksRaw(int nargs,
  249. RunCallbacksMode mode, const char *fxn)
  250. {
  251. #ifndef SERVER
  252. // Hard fail for bad guarded callbacks
  253. // Only run callbacks when the scripting enviroment is loaded
  254. FATAL_ERROR_IF(m_type == ScriptingType::Client &&
  255. !getClient()->modsLoaded(), fxn);
  256. #endif
  257. #ifdef SCRIPTAPI_LOCK_DEBUG
  258. assert(m_lock_recursion_count > 0);
  259. #endif
  260. lua_State *L = getStack();
  261. FATAL_ERROR_IF(lua_gettop(L) < nargs + 1, "Not enough arguments");
  262. // Insert error handler
  263. PUSH_ERROR_HANDLER(L);
  264. int error_handler = lua_gettop(L) - nargs - 1;
  265. lua_insert(L, error_handler);
  266. // Insert run_callbacks between error handler and table
  267. lua_getglobal(L, "core");
  268. lua_getfield(L, -1, "run_callbacks");
  269. lua_remove(L, -2);
  270. lua_insert(L, error_handler + 1);
  271. // Insert mode after table
  272. lua_pushnumber(L, (int)mode);
  273. lua_insert(L, error_handler + 3);
  274. // Stack now looks like this:
  275. // ... <error handler> <run_callbacks> <table> <mode> <arg#1> <arg#2> ... <arg#n>
  276. int result = lua_pcall(L, nargs + 2, 1, error_handler);
  277. if (result != 0)
  278. scriptError(result, fxn);
  279. lua_remove(L, error_handler);
  280. }
  281. void ScriptApiBase::realityCheck()
  282. {
  283. int top = lua_gettop(m_luastack);
  284. if (top >= 30) {
  285. dstream << "Stack is over 30:" << std::endl;
  286. stackDump(dstream);
  287. std::string traceback = script_get_backtrace(m_luastack);
  288. throw LuaError("Stack is over 30 (reality check)\n" + traceback);
  289. }
  290. }
  291. void ScriptApiBase::scriptError(int result, const char *fxn)
  292. {
  293. script_error(getStack(), result, m_last_run_mod.c_str(), fxn);
  294. }
  295. void ScriptApiBase::stackDump(std::ostream &o)
  296. {
  297. int top = lua_gettop(m_luastack);
  298. for (int i = 1; i <= top; i++) { /* repeat for each level */
  299. int t = lua_type(m_luastack, i);
  300. switch (t) {
  301. case LUA_TSTRING: /* strings */
  302. o << "\"" << readParam<std::string>(m_luastack, i) << "\"";
  303. break;
  304. case LUA_TBOOLEAN: /* booleans */
  305. o << (readParam<bool>(m_luastack, i) ? "true" : "false");
  306. break;
  307. case LUA_TNUMBER: /* numbers */ {
  308. char buf[10];
  309. porting::mt_snprintf(buf, sizeof(buf), "%lf", lua_tonumber(m_luastack, i));
  310. o << buf;
  311. break;
  312. }
  313. default: /* other values */
  314. o << lua_typename(m_luastack, t);
  315. break;
  316. }
  317. o << " ";
  318. }
  319. o << std::endl;
  320. }
  321. void ScriptApiBase::setOriginDirect(const char *origin)
  322. {
  323. m_last_run_mod = origin ? origin : "??";
  324. }
  325. void ScriptApiBase::setOriginFromTableRaw(int index, const char *fxn)
  326. {
  327. lua_State *L = getStack();
  328. m_last_run_mod = lua_istable(L, index) ?
  329. getstringfield_default(L, index, "mod_origin", "") : "";
  330. }
  331. /*
  332. * How ObjectRefs are handled in Lua:
  333. * When an active object is created, an ObjectRef is created on the Lua side
  334. * and stored in core.object_refs[id].
  335. * Methods that require an ObjectRef to a certain object retrieve it from that
  336. * table instead of creating their own.(*)
  337. * When an active object is removed, the existing ObjectRef is invalidated
  338. * using ::set_null() and removed from the core.object_refs table.
  339. * (*) An exception to this are NULL ObjectRefs and anonymous ObjectRefs
  340. * for objects without ID.
  341. * It's unclear what the latter are needed for and their use is problematic
  342. * since we lose control over the ref and the contained pointer.
  343. */
  344. void ScriptApiBase::addObjectReference(ServerActiveObject *cobj)
  345. {
  346. SCRIPTAPI_PRECHECKHEADER
  347. //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
  348. // Create object on stack
  349. ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
  350. int object = lua_gettop(L);
  351. // Get core.object_refs table
  352. lua_getglobal(L, "core");
  353. lua_getfield(L, -1, "object_refs");
  354. luaL_checktype(L, -1, LUA_TTABLE);
  355. int objectstable = lua_gettop(L);
  356. // object_refs[id] = object
  357. lua_pushnumber(L, cobj->getId()); // Push id
  358. lua_pushvalue(L, object); // Copy object to top of stack
  359. lua_settable(L, objectstable);
  360. }
  361. void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj)
  362. {
  363. SCRIPTAPI_PRECHECKHEADER
  364. //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
  365. // Get core.object_refs table
  366. lua_getglobal(L, "core");
  367. lua_getfield(L, -1, "object_refs");
  368. luaL_checktype(L, -1, LUA_TTABLE);
  369. int objectstable = lua_gettop(L);
  370. // Get object_refs[id]
  371. lua_pushnumber(L, cobj->getId()); // Push id
  372. lua_gettable(L, objectstable);
  373. // Set object reference to NULL
  374. ObjectRef::set_null(L);
  375. lua_pop(L, 1); // pop object
  376. // Set object_refs[id] = nil
  377. lua_pushnumber(L, cobj->getId()); // Push id
  378. lua_pushnil(L);
  379. lua_settable(L, objectstable);
  380. }
  381. // Creates a new anonymous reference if cobj=NULL or id=0
  382. void ScriptApiBase::objectrefGetOrCreate(lua_State *L,
  383. ServerActiveObject *cobj)
  384. {
  385. if (cobj == NULL || cobj->getId() == 0) {
  386. ObjectRef::create(L, cobj);
  387. } else {
  388. push_objectRef(L, cobj->getId());
  389. if (cobj->isGone())
  390. warningstream << "ScriptApiBase::objectrefGetOrCreate(): "
  391. << "Pushing ObjectRef to removed/deactivated object"
  392. << ", this is probably a bug." << std::endl;
  393. }
  394. }
  395. void ScriptApiBase::pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason &reason)
  396. {
  397. if (reason.hasLuaReference())
  398. lua_rawgeti(L, LUA_REGISTRYINDEX, reason.lua_reference);
  399. else
  400. lua_newtable(L);
  401. lua_getfield(L, -1, "type");
  402. bool has_type = (bool)lua_isstring(L, -1);
  403. lua_pop(L, 1);
  404. if (!has_type) {
  405. lua_pushstring(L, reason.getTypeAsString().c_str());
  406. lua_setfield(L, -2, "type");
  407. }
  408. lua_pushstring(L, reason.from_mod ? "mod" : "engine");
  409. lua_setfield(L, -2, "from");
  410. if (reason.object) {
  411. objectrefGetOrCreate(L, reason.object);
  412. lua_setfield(L, -2, "object");
  413. }
  414. if (!reason.node.empty()) {
  415. lua_pushstring(L, reason.node.c_str());
  416. lua_setfield(L, -2, "node");
  417. }
  418. }
  419. Server* ScriptApiBase::getServer()
  420. {
  421. return dynamic_cast<Server *>(m_gamedef);
  422. }
  423. #ifndef SERVER
  424. Client* ScriptApiBase::getClient()
  425. {
  426. return dynamic_cast<Client *>(m_gamedef);
  427. }
  428. #endif