You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

322 lines
9.2 KiB

  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_Remove(u16 id)
  88. {
  89. SCRIPTAPI_PRECHECKHEADER
  90. verbosestream << "scriptapi_luaentity_rm: id=" << id << std::endl;
  91. // Get core.luaentities table
  92. lua_getglobal(L, "core");
  93. lua_getfield(L, -1, "luaentities");
  94. luaL_checktype(L, -1, LUA_TTABLE);
  95. int objectstable = lua_gettop(L);
  96. // Set luaentities[id] = nil
  97. lua_pushnumber(L, id); // Push id
  98. lua_pushnil(L);
  99. lua_settable(L, objectstable);
  100. lua_pop(L, 2); // pop luaentities, core
  101. }
  102. std::string ScriptApiEntity::luaentity_GetStaticdata(u16 id)
  103. {
  104. SCRIPTAPI_PRECHECKHEADER
  105. //infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
  106. int error_handler = PUSH_ERROR_HANDLER(L);
  107. // Get core.luaentities[id]
  108. luaentity_get(L, id);
  109. int object = lua_gettop(L);
  110. // Get get_staticdata function
  111. lua_getfield(L, -1, "get_staticdata");
  112. if (lua_isnil(L, -1)) {
  113. lua_pop(L, 2); // Pop entity and get_staticdata
  114. return "";
  115. }
  116. luaL_checktype(L, -1, LUA_TFUNCTION);
  117. lua_pushvalue(L, object); // self
  118. setOriginFromTable(object);
  119. PCALL_RES(lua_pcall(L, 1, 1, error_handler));
  120. lua_remove(L, object);
  121. lua_remove(L, error_handler);
  122. size_t len = 0;
  123. const char *s = lua_tolstring(L, -1, &len);
  124. lua_pop(L, 1); // Pop static data
  125. return std::string(s, len);
  126. }
  127. void ScriptApiEntity::luaentity_GetProperties(u16 id,
  128. ObjectProperties *prop)
  129. {
  130. SCRIPTAPI_PRECHECKHEADER
  131. //infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
  132. // Get core.luaentities[id]
  133. luaentity_get(L, id);
  134. // Set default values that differ from ObjectProperties defaults
  135. prop->hp_max = 10;
  136. /* Read stuff */
  137. prop->hp_max = getintfield_default(L, -1, "hp_max", 10);
  138. getboolfield(L, -1, "physical", prop->physical);
  139. getboolfield(L, -1, "collide_with_objects", prop->collideWithObjects);
  140. getfloatfield(L, -1, "weight", prop->weight);
  141. lua_getfield(L, -1, "collisionbox");
  142. if (lua_istable(L, -1))
  143. prop->collisionbox = read_aabb3f(L, -1, 1.0);
  144. lua_pop(L, 1);
  145. getstringfield(L, -1, "visual", prop->visual);
  146. getstringfield(L, -1, "mesh", prop->mesh);
  147. // Deprecated: read object properties directly
  148. read_object_properties(L, -1, prop, getServer()->idef());
  149. // Read initial_properties
  150. lua_getfield(L, -1, "initial_properties");
  151. read_object_properties(L, -1, prop, getServer()->idef());
  152. lua_pop(L, 1);
  153. }
  154. void ScriptApiEntity::luaentity_Step(u16 id, float dtime)
  155. {
  156. SCRIPTAPI_PRECHECKHEADER
  157. //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
  158. int error_handler = PUSH_ERROR_HANDLER(L);
  159. // Get core.luaentities[id]
  160. luaentity_get(L, id);
  161. int object = lua_gettop(L);
  162. // State: object is at top of stack
  163. // Get step function
  164. lua_getfield(L, -1, "on_step");
  165. if (lua_isnil(L, -1)) {
  166. lua_pop(L, 2); // Pop on_step and entity
  167. return;
  168. }
  169. luaL_checktype(L, -1, LUA_TFUNCTION);
  170. lua_pushvalue(L, object); // self
  171. lua_pushnumber(L, dtime); // dtime
  172. setOriginFromTable(object);
  173. PCALL_RES(lua_pcall(L, 2, 0, error_handler));
  174. lua_pop(L, 2); // Pop object and error handler
  175. }
  176. // Calls entity:on_punch(ObjectRef puncher, time_from_last_punch,
  177. // tool_capabilities, direction, damage)
  178. bool ScriptApiEntity::luaentity_Punch(u16 id,
  179. ServerActiveObject *puncher, float time_from_last_punch,
  180. const ToolCapabilities *toolcap, v3f dir, s16 damage)
  181. {
  182. SCRIPTAPI_PRECHECKHEADER
  183. //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
  184. int error_handler = PUSH_ERROR_HANDLER(L);
  185. // Get core.luaentities[id]
  186. luaentity_get(L,id);
  187. int object = lua_gettop(L);
  188. // State: object is at top of stack
  189. // Get function
  190. lua_getfield(L, -1, "on_punch");
  191. if (lua_isnil(L, -1)) {
  192. lua_pop(L, 2); // Pop on_punch and entity
  193. return false;
  194. }
  195. luaL_checktype(L, -1, LUA_TFUNCTION);
  196. lua_pushvalue(L, object); // self
  197. objectrefGetOrCreate(L, puncher); // Clicker reference
  198. lua_pushnumber(L, time_from_last_punch);
  199. push_tool_capabilities(L, *toolcap);
  200. push_v3f(L, dir);
  201. lua_pushnumber(L, damage);
  202. setOriginFromTable(object);
  203. PCALL_RES(lua_pcall(L, 6, 1, error_handler));
  204. bool retval = readParam<bool>(L, -1);
  205. lua_pop(L, 2); // Pop object and error handler
  206. return retval;
  207. }
  208. bool ScriptApiEntity::luaentity_on_death(u16 id, ServerActiveObject *killer)
  209. {
  210. SCRIPTAPI_PRECHECKHEADER
  211. int error_handler = PUSH_ERROR_HANDLER(L);
  212. // Get core.luaentities[id]
  213. luaentity_get(L, id);
  214. int object = lua_gettop(L);
  215. // State: object is at top of stack
  216. // Get function
  217. lua_getfield(L, -1, "on_death");
  218. if (lua_isnil(L, -1)) {
  219. lua_pop(L, 2); // Pop on_death and entity
  220. return false;
  221. }
  222. luaL_checktype(L, -1, LUA_TFUNCTION);
  223. lua_pushvalue(L, object); // self
  224. objectrefGetOrCreate(L, killer); // killer reference
  225. setOriginFromTable(object);
  226. PCALL_RES(lua_pcall(L, 2, 1, error_handler));
  227. bool retval = readParam<bool>(L, -1);
  228. lua_pop(L, 2); // Pop object and error handler
  229. return retval;
  230. }
  231. // Calls entity:on_rightclick(ObjectRef clicker)
  232. void ScriptApiEntity::luaentity_Rightclick(u16 id,
  233. ServerActiveObject *clicker)
  234. {
  235. SCRIPTAPI_PRECHECKHEADER
  236. //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
  237. int error_handler = PUSH_ERROR_HANDLER(L);
  238. // Get core.luaentities[id]
  239. luaentity_get(L, id);
  240. int object = lua_gettop(L);
  241. // State: object is at top of stack
  242. // Get function
  243. lua_getfield(L, -1, "on_rightclick");
  244. if (lua_isnil(L, -1)) {
  245. lua_pop(L, 2); // Pop on_rightclick and entity
  246. return;
  247. }
  248. luaL_checktype(L, -1, LUA_TFUNCTION);
  249. lua_pushvalue(L, object); // self
  250. objectrefGetOrCreate(L, clicker); // Clicker reference
  251. setOriginFromTable(object);
  252. PCALL_RES(lua_pcall(L, 2, 0, error_handler));
  253. lua_pop(L, 2); // Pop object and error handler
  254. }