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.
 
 
 
 
 
 

365 lines
11 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_player.h"
  17. #include "cpp_api/s_internal.h"
  18. #include "common/c_converter.h"
  19. #include "common/c_content.h"
  20. #include "debug.h"
  21. #include "inventorymanager.h"
  22. #include "lua_api/l_inventory.h"
  23. #include "lua_api/l_item.h"
  24. #include "util/string.h"
  25. void ScriptApiPlayer::on_newplayer(ServerActiveObject *player)
  26. {
  27. SCRIPTAPI_PRECHECKHEADER
  28. // Get core.registered_on_newplayers
  29. lua_getglobal(L, "core");
  30. lua_getfield(L, -1, "registered_on_newplayers");
  31. // Call callbacks
  32. objectrefGetOrCreate(L, player);
  33. runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
  34. }
  35. void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player, const PlayerHPChangeReason &reason)
  36. {
  37. SCRIPTAPI_PRECHECKHEADER
  38. // Get callback table
  39. lua_getglobal(L, "core");
  40. lua_getfield(L, -1, "registered_on_dieplayers");
  41. // Push arguments
  42. objectrefGetOrCreate(L, player);
  43. pushPlayerHPChangeReason(L, reason);
  44. // Run callbacks
  45. runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
  46. }
  47. bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player,
  48. ServerActiveObject *hitter,
  49. float time_from_last_punch,
  50. const ToolCapabilities *toolcap,
  51. v3f dir,
  52. s16 damage)
  53. {
  54. SCRIPTAPI_PRECHECKHEADER
  55. // Get core.registered_on_punchplayers
  56. lua_getglobal(L, "core");
  57. lua_getfield(L, -1, "registered_on_punchplayers");
  58. // Call callbacks
  59. objectrefGetOrCreate(L, player);
  60. objectrefGetOrCreate(L, hitter);
  61. lua_pushnumber(L, time_from_last_punch);
  62. push_tool_capabilities(L, *toolcap);
  63. push_v3f(L, dir);
  64. lua_pushnumber(L, damage);
  65. runCallbacks(6, RUN_CALLBACKS_MODE_OR);
  66. return readParam<bool>(L, -1);
  67. }
  68. s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player,
  69. s16 hp_change, const PlayerHPChangeReason &reason)
  70. {
  71. SCRIPTAPI_PRECHECKHEADER
  72. int error_handler = PUSH_ERROR_HANDLER(L);
  73. // Get core.registered_on_player_hpchange
  74. lua_getglobal(L, "core");
  75. lua_getfield(L, -1, "registered_on_player_hpchange");
  76. lua_remove(L, -2);
  77. // Push arguments
  78. objectrefGetOrCreate(L, player);
  79. lua_pushnumber(L, hp_change);
  80. pushPlayerHPChangeReason(L, reason);
  81. // Call callbacks
  82. PCALL_RES(lua_pcall(L, 3, 1, error_handler));
  83. hp_change = lua_tointeger(L, -1);
  84. lua_pop(L, 2); // Pop result and error handler
  85. return hp_change;
  86. }
  87. bool ScriptApiPlayer::on_respawnplayer(ServerActiveObject *player)
  88. {
  89. SCRIPTAPI_PRECHECKHEADER
  90. // Get core.registered_on_respawnplayers
  91. lua_getglobal(L, "core");
  92. lua_getfield(L, -1, "registered_on_respawnplayers");
  93. // Call callbacks
  94. objectrefGetOrCreate(L, player);
  95. runCallbacks(1, RUN_CALLBACKS_MODE_OR);
  96. return readParam<bool>(L, -1);
  97. }
  98. bool ScriptApiPlayer::on_prejoinplayer(
  99. const std::string &name,
  100. const std::string &ip,
  101. std::string *reason)
  102. {
  103. SCRIPTAPI_PRECHECKHEADER
  104. // Get core.registered_on_prejoinplayers
  105. lua_getglobal(L, "core");
  106. lua_getfield(L, -1, "registered_on_prejoinplayers");
  107. lua_pushstring(L, name.c_str());
  108. lua_pushstring(L, ip.c_str());
  109. runCallbacks(2, RUN_CALLBACKS_MODE_OR);
  110. if (lua_isstring(L, -1)) {
  111. reason->assign(readParam<std::string>(L, -1));
  112. return true;
  113. }
  114. return false;
  115. }
  116. bool ScriptApiPlayer::can_bypass_userlimit(const std::string &name, const std::string &ip)
  117. {
  118. SCRIPTAPI_PRECHECKHEADER
  119. // Get core.registered_on_prejoinplayers
  120. lua_getglobal(L, "core");
  121. lua_getfield(L, -1, "registered_can_bypass_userlimit");
  122. lua_pushstring(L, name.c_str());
  123. lua_pushstring(L, ip.c_str());
  124. runCallbacks(2, RUN_CALLBACKS_MODE_OR);
  125. return lua_toboolean(L, -1);
  126. }
  127. void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player)
  128. {
  129. SCRIPTAPI_PRECHECKHEADER
  130. // Get core.registered_on_joinplayers
  131. lua_getglobal(L, "core");
  132. lua_getfield(L, -1, "registered_on_joinplayers");
  133. // Call callbacks
  134. objectrefGetOrCreate(L, player);
  135. runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
  136. }
  137. void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player,
  138. bool timeout)
  139. {
  140. SCRIPTAPI_PRECHECKHEADER
  141. // Get core.registered_on_leaveplayers
  142. lua_getglobal(L, "core");
  143. lua_getfield(L, -1, "registered_on_leaveplayers");
  144. // Call callbacks
  145. objectrefGetOrCreate(L, player);
  146. lua_pushboolean(L, timeout);
  147. runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
  148. }
  149. void ScriptApiPlayer::on_cheat(ServerActiveObject *player,
  150. const std::string &cheat_type)
  151. {
  152. SCRIPTAPI_PRECHECKHEADER
  153. // Get core.registered_on_cheats
  154. lua_getglobal(L, "core");
  155. lua_getfield(L, -1, "registered_on_cheats");
  156. // Call callbacks
  157. objectrefGetOrCreate(L, player);
  158. lua_newtable(L);
  159. lua_pushlstring(L, cheat_type.c_str(), cheat_type.size());
  160. lua_setfield(L, -2, "type");
  161. runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
  162. }
  163. void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player,
  164. const std::string &formname,
  165. const StringMap &fields)
  166. {
  167. SCRIPTAPI_PRECHECKHEADER
  168. // Get core.registered_on_chat_messages
  169. lua_getglobal(L, "core");
  170. lua_getfield(L, -1, "registered_on_player_receive_fields");
  171. // Call callbacks
  172. // param 1
  173. objectrefGetOrCreate(L, player);
  174. // param 2
  175. lua_pushstring(L, formname.c_str());
  176. // param 3
  177. lua_newtable(L);
  178. StringMap::const_iterator it;
  179. for (it = fields.begin(); it != fields.end(); ++it) {
  180. const std::string &name = it->first;
  181. const std::string &value = it->second;
  182. lua_pushstring(L, name.c_str());
  183. lua_pushlstring(L, value.c_str(), value.size());
  184. lua_settable(L, -3);
  185. }
  186. runCallbacks(3, RUN_CALLBACKS_MODE_OR_SC);
  187. }
  188. ScriptApiPlayer::~ScriptApiPlayer()
  189. {
  190. }
  191. void ScriptApiPlayer::pushMoveArguments(
  192. const InventoryLocation &loc,
  193. const std::string &from_list, int from_index,
  194. const std::string &to_list, int to_index,
  195. int count, ServerActiveObject *player)
  196. {
  197. lua_State *L = getStack();
  198. objectrefGetOrCreate(L, player); // player
  199. lua_pushstring(L, "move"); // action
  200. InvRef::create(L, loc); // inventory
  201. lua_newtable(L);
  202. {
  203. // Table containing the action information
  204. lua_pushstring(L, from_list.c_str());
  205. lua_setfield(L, -2, "from_list");
  206. lua_pushstring(L, to_list.c_str());
  207. lua_setfield(L, -2, "to_list");
  208. lua_pushinteger(L, from_index + 1);
  209. lua_setfield(L, -2, "from_index");
  210. lua_pushinteger(L, to_index + 1);
  211. lua_setfield(L, -2, "to_index");
  212. lua_pushinteger(L, count);
  213. lua_setfield(L, -2, "count");
  214. }
  215. }
  216. void ScriptApiPlayer::pushPutTakeArguments(
  217. const char *method, const InventoryLocation &loc,
  218. const std::string &listname, int index, const ItemStack &stack,
  219. ServerActiveObject *player)
  220. {
  221. lua_State *L = getStack();
  222. objectrefGetOrCreate(L, player); // player
  223. lua_pushstring(L, method); // action
  224. InvRef::create(L, loc); // inventory
  225. lua_newtable(L);
  226. {
  227. // Table containing the action information
  228. lua_pushstring(L, listname.c_str());
  229. lua_setfield(L, -2, "listname");
  230. lua_pushinteger(L, index + 1);
  231. lua_setfield(L, -2, "index");
  232. LuaItemStack::create(L, stack);
  233. lua_setfield(L, -2, "stack");
  234. }
  235. }
  236. // Return number of accepted items to be moved
  237. int ScriptApiPlayer::player_inventory_AllowMove(
  238. const InventoryLocation &loc,
  239. const std::string &from_list, int from_index,
  240. const std::string &to_list, int to_index,
  241. int count, ServerActiveObject *player)
  242. {
  243. SCRIPTAPI_PRECHECKHEADER
  244. lua_getglobal(L, "core");
  245. lua_getfield(L, -1, "registered_allow_player_inventory_actions");
  246. pushMoveArguments(loc, from_list, from_index, to_list, to_index, count, player);
  247. runCallbacks(4, RUN_CALLBACKS_MODE_OR_SC);
  248. return lua_type(L, -1) == LUA_TNUMBER ? lua_tonumber(L, -1) : count;
  249. }
  250. // Return number of accepted items to be put
  251. int ScriptApiPlayer::player_inventory_AllowPut(
  252. const InventoryLocation &loc,
  253. const std::string &listname, int index, const ItemStack &stack,
  254. ServerActiveObject *player)
  255. {
  256. SCRIPTAPI_PRECHECKHEADER
  257. lua_getglobal(L, "core");
  258. lua_getfield(L, -1, "registered_allow_player_inventory_actions");
  259. pushPutTakeArguments("put", loc, listname, index, stack, player);
  260. runCallbacks(4, RUN_CALLBACKS_MODE_OR_SC);
  261. return lua_type(L, -1) == LUA_TNUMBER ? lua_tonumber(L, -1) : stack.count;
  262. }
  263. // Return number of accepted items to be taken
  264. int ScriptApiPlayer::player_inventory_AllowTake(
  265. const InventoryLocation &loc,
  266. const std::string &listname, int index, const ItemStack &stack,
  267. ServerActiveObject *player)
  268. {
  269. SCRIPTAPI_PRECHECKHEADER
  270. lua_getglobal(L, "core");
  271. lua_getfield(L, -1, "registered_allow_player_inventory_actions");
  272. pushPutTakeArguments("take", loc, listname, index, stack, player);
  273. runCallbacks(4, RUN_CALLBACKS_MODE_OR_SC);
  274. return lua_type(L, -1) == LUA_TNUMBER ? lua_tonumber(L, -1) : stack.count;
  275. }
  276. // Report moved items
  277. void ScriptApiPlayer::player_inventory_OnMove(
  278. const InventoryLocation &loc,
  279. const std::string &from_list, int from_index,
  280. const std::string &to_list, int to_index,
  281. int count, ServerActiveObject *player)
  282. {
  283. SCRIPTAPI_PRECHECKHEADER
  284. lua_getglobal(L, "core");
  285. lua_getfield(L, -1, "registered_on_player_inventory_actions");
  286. pushMoveArguments(loc, from_list, from_index, to_list, to_index, count, player);
  287. runCallbacks(4, RUN_CALLBACKS_MODE_FIRST);
  288. }
  289. // Report put items
  290. void ScriptApiPlayer::player_inventory_OnPut(
  291. const InventoryLocation &loc,
  292. const std::string &listname, int index, const ItemStack &stack,
  293. ServerActiveObject *player)
  294. {
  295. SCRIPTAPI_PRECHECKHEADER
  296. lua_getglobal(L, "core");
  297. lua_getfield(L, -1, "registered_on_player_inventory_actions");
  298. pushPutTakeArguments("put", loc, listname, index, stack, player);
  299. runCallbacks(4, RUN_CALLBACKS_MODE_FIRST);
  300. }
  301. // Report taken items
  302. void ScriptApiPlayer::player_inventory_OnTake(
  303. const InventoryLocation &loc,
  304. const std::string &listname, int index, const ItemStack &stack,
  305. ServerActiveObject *player)
  306. {
  307. SCRIPTAPI_PRECHECKHEADER
  308. lua_getglobal(L, "core");
  309. lua_getfield(L, -1, "registered_on_player_inventory_actions");
  310. pushPutTakeArguments("take", loc, listname, index, stack, player);
  311. runCallbacks(4, RUN_CALLBACKS_MODE_FIRST);
  312. }