s_entity.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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_entity.h"
  17. #include "cpp_api/s_internal.h"
  18. #include "log.h"
  19. #include "object_properties.h"
  20. #include "common/c_converter.h"
  21. #include "common/c_content.h"
  22. #include "server.h"
  23. bool ScriptApiEntity::luaentity_Add(u16 id, const char *name)
  24. {
  25. SCRIPTAPI_PRECHECKHEADER
  26. verbosestream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
  27. <<name<<"\""<<std::endl;
  28. // Get core.registered_entities[name]
  29. lua_getglobal(L, "core");
  30. lua_getfield(L, -1, "registered_entities");
  31. luaL_checktype(L, -1, LUA_TTABLE);
  32. lua_pushstring(L, name);
  33. lua_gettable(L, -2);
  34. // Should be a table, which we will use as a prototype
  35. //luaL_checktype(L, -1, LUA_TTABLE);
  36. if (lua_type(L, -1) != LUA_TTABLE){
  37. errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
  38. return false;
  39. }
  40. int prototype_table = lua_gettop(L);
  41. //dump2(L, "prototype_table");
  42. // Create entity object
  43. lua_newtable(L);
  44. int object = lua_gettop(L);
  45. // Set object metatable
  46. lua_pushvalue(L, prototype_table);
  47. lua_setmetatable(L, -2);
  48. // Add object reference
  49. // This should be userdata with metatable ObjectRef
  50. push_objectRef(L, id);
  51. luaL_checktype(L, -1, LUA_TUSERDATA);
  52. if (!luaL_checkudata(L, -1, "ObjectRef"))
  53. luaL_typerror(L, -1, "ObjectRef");
  54. lua_setfield(L, -2, "object");
  55. // core.luaentities[id] = object
  56. lua_getglobal(L, "core");
  57. lua_getfield(L, -1, "luaentities");
  58. luaL_checktype(L, -1, LUA_TTABLE);
  59. lua_pushnumber(L, id); // Push id
  60. lua_pushvalue(L, object); // Copy object to top of stack
  61. lua_settable(L, -3);
  62. return true;
  63. }
  64. void ScriptApiEntity::luaentity_Activate(u16 id,
  65. const std::string &staticdata, u32 dtime_s)
  66. {
  67. SCRIPTAPI_PRECHECKHEADER
  68. verbosestream << "scriptapi_luaentity_activate: id=" << id << std::endl;
  69. int error_handler = PUSH_ERROR_HANDLER(L);
  70. // Get core.luaentities[id]
  71. luaentity_get(L, id);
  72. int object = lua_gettop(L);
  73. // Get on_activate function
  74. lua_getfield(L, -1, "on_activate");
  75. if (!lua_isnil(L, -1)) {
  76. luaL_checktype(L, -1, LUA_TFUNCTION);
  77. lua_pushvalue(L, object); // self
  78. lua_pushlstring(L, staticdata.c_str(), staticdata.size());
  79. lua_pushinteger(L, dtime_s);
  80. setOriginFromTable(object);
  81. PCALL_RES(lua_pcall(L, 3, 0, error_handler));
  82. } else {
  83. lua_pop(L, 1);
  84. }
  85. lua_pop(L, 2); // Pop object and error handler
  86. }
  87. void ScriptApiEntity::luaentity_Deactivate(u16 id, bool removal)
  88. {
  89. SCRIPTAPI_PRECHECKHEADER
  90. verbosestream << "scriptapi_luaentity_deactivate: id=" << id << std::endl;
  91. int error_handler = PUSH_ERROR_HANDLER(L);
  92. // Get the entity
  93. luaentity_get(L, id);
  94. int object = lua_gettop(L);
  95. // Get on_deactivate
  96. lua_getfield(L, -1, "on_deactivate");
  97. if (!lua_isnil(L, -1)) {
  98. luaL_checktype(L, -1, LUA_TFUNCTION);
  99. lua_pushvalue(L, object);
  100. lua_pushboolean(L, removal);
  101. setOriginFromTable(object);
  102. PCALL_RES(lua_pcall(L, 2, 0, error_handler));
  103. } else {
  104. lua_pop(L, 1);
  105. }
  106. lua_pop(L, 2); // Pop object and error handler
  107. }
  108. void ScriptApiEntity::luaentity_Remove(u16 id)
  109. {
  110. SCRIPTAPI_PRECHECKHEADER
  111. verbosestream << "scriptapi_luaentity_rm: id=" << id << std::endl;
  112. // Get core.luaentities table
  113. lua_getglobal(L, "core");
  114. lua_getfield(L, -1, "luaentities");
  115. luaL_checktype(L, -1, LUA_TTABLE);
  116. int objectstable = lua_gettop(L);
  117. // Set luaentities[id] = nil
  118. lua_pushnumber(L, id); // Push id
  119. lua_pushnil(L);
  120. lua_settable(L, objectstable);
  121. lua_pop(L, 2); // pop luaentities, core
  122. }
  123. std::string ScriptApiEntity::luaentity_GetStaticdata(u16 id)
  124. {
  125. SCRIPTAPI_PRECHECKHEADER
  126. //infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
  127. int error_handler = PUSH_ERROR_HANDLER(L);
  128. // Get core.luaentities[id]
  129. luaentity_get(L, id);
  130. int object = lua_gettop(L);
  131. // Get get_staticdata function
  132. lua_getfield(L, -1, "get_staticdata");
  133. if (lua_isnil(L, -1)) {
  134. lua_pop(L, 2); // Pop entity and get_staticdata
  135. return "";
  136. }
  137. luaL_checktype(L, -1, LUA_TFUNCTION);
  138. lua_pushvalue(L, object); // self
  139. setOriginFromTable(object);
  140. PCALL_RES(lua_pcall(L, 1, 1, error_handler));
  141. lua_remove(L, object);
  142. lua_remove(L, error_handler);
  143. size_t len = 0;
  144. const char *s = lua_tolstring(L, -1, &len);
  145. lua_pop(L, 1); // Pop static data
  146. return std::string(s, len);
  147. }
  148. void ScriptApiEntity::luaentity_GetProperties(u16 id,
  149. ServerActiveObject *self, ObjectProperties *prop)
  150. {
  151. SCRIPTAPI_PRECHECKHEADER
  152. //infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
  153. // Get core.luaentities[id]
  154. luaentity_get(L, id);
  155. // Set default values that differ from ObjectProperties defaults
  156. prop->hp_max = 10;
  157. // Deprecated: read object properties directly
  158. read_object_properties(L, -1, self, prop, getServer()->idef());
  159. // Read initial_properties
  160. lua_getfield(L, -1, "initial_properties");
  161. read_object_properties(L, -1, self, prop, getServer()->idef());
  162. lua_pop(L, 1);
  163. }
  164. void ScriptApiEntity::luaentity_Step(u16 id, float dtime,
  165. const collisionMoveResult *moveresult)
  166. {
  167. SCRIPTAPI_PRECHECKHEADER
  168. int error_handler = PUSH_ERROR_HANDLER(L);
  169. // Get core.luaentities[id]
  170. luaentity_get(L, id);
  171. int object = lua_gettop(L);
  172. // State: object is at top of stack
  173. // Get step function
  174. lua_getfield(L, -1, "on_step");
  175. if (lua_isnil(L, -1)) {
  176. lua_pop(L, 2); // Pop on_step and entity
  177. return;
  178. }
  179. luaL_checktype(L, -1, LUA_TFUNCTION);
  180. lua_pushvalue(L, object); // self
  181. lua_pushnumber(L, dtime); // dtime
  182. /* moveresult */
  183. if (moveresult)
  184. push_collision_move_result(L, *moveresult);
  185. else
  186. lua_pushnil(L);
  187. setOriginFromTable(object);
  188. PCALL_RES(lua_pcall(L, 3, 0, error_handler));
  189. lua_pop(L, 2); // Pop object and error handler
  190. }
  191. // Calls entity:on_punch(ObjectRef puncher, time_from_last_punch,
  192. // tool_capabilities, direction, damage)
  193. bool ScriptApiEntity::luaentity_Punch(u16 id,
  194. ServerActiveObject *puncher, float time_from_last_punch,
  195. const ToolCapabilities *toolcap, v3f dir, s32 damage)
  196. {
  197. SCRIPTAPI_PRECHECKHEADER
  198. assert(puncher);
  199. int error_handler = PUSH_ERROR_HANDLER(L);
  200. // Get core.luaentities[id]
  201. luaentity_get(L,id);
  202. int object = lua_gettop(L);
  203. // State: object is at top of stack
  204. // Get function
  205. lua_getfield(L, -1, "on_punch");
  206. if (lua_isnil(L, -1)) {
  207. lua_pop(L, 2); // Pop on_punch and entity
  208. return false;
  209. }
  210. luaL_checktype(L, -1, LUA_TFUNCTION);
  211. lua_pushvalue(L, object); // self
  212. objectrefGetOrCreate(L, puncher); // Clicker reference
  213. lua_pushnumber(L, time_from_last_punch);
  214. push_tool_capabilities(L, *toolcap);
  215. push_v3f(L, dir);
  216. lua_pushnumber(L, damage);
  217. setOriginFromTable(object);
  218. PCALL_RES(lua_pcall(L, 6, 1, error_handler));
  219. bool retval = readParam<bool>(L, -1);
  220. lua_pop(L, 2); // Pop object and error handler
  221. return retval;
  222. }
  223. // Calls entity[field](ObjectRef self, ObjectRef sao)
  224. bool ScriptApiEntity::luaentity_run_simple_callback(u16 id,
  225. ServerActiveObject *sao, const char *field)
  226. {
  227. SCRIPTAPI_PRECHECKHEADER
  228. int error_handler = PUSH_ERROR_HANDLER(L);
  229. // Get core.luaentities[id]
  230. luaentity_get(L, id);
  231. int object = lua_gettop(L);
  232. // State: object is at top of stack
  233. // Get function
  234. lua_getfield(L, -1, field);
  235. if (lua_isnil(L, -1)) {
  236. lua_pop(L, 2); // Pop callback field and entity
  237. return false;
  238. }
  239. luaL_checktype(L, -1, LUA_TFUNCTION);
  240. lua_pushvalue(L, object); // self
  241. if (sao)
  242. objectrefGetOrCreate(L, sao); // sao reference
  243. else
  244. lua_pushnil(L);
  245. setOriginFromTable(object);
  246. PCALL_RES(lua_pcall(L, 2, 1, error_handler));
  247. bool retval = readParam<bool>(L, -1);
  248. lua_pop(L, 2); // Pop object and error handler
  249. return retval;
  250. }
  251. bool ScriptApiEntity::luaentity_on_death(u16 id, ServerActiveObject *killer)
  252. {
  253. return luaentity_run_simple_callback(id, killer, "on_death");
  254. }
  255. // Calls entity:on_rightclick(ObjectRef clicker)
  256. void ScriptApiEntity::luaentity_Rightclick(u16 id, ServerActiveObject *clicker)
  257. {
  258. luaentity_run_simple_callback(id, clicker, "on_rightclick");
  259. }
  260. void ScriptApiEntity::luaentity_on_attach_child(u16 id, ServerActiveObject *child)
  261. {
  262. luaentity_run_simple_callback(id, child, "on_attach_child");
  263. }
  264. void ScriptApiEntity::luaentity_on_detach_child(u16 id, ServerActiveObject *child)
  265. {
  266. luaentity_run_simple_callback(id, child, "on_detach_child");
  267. }
  268. void ScriptApiEntity::luaentity_on_detach(u16 id, ServerActiveObject *parent)
  269. {
  270. luaentity_run_simple_callback(id, parent, "on_detach");
  271. }