s_inventory.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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_inventory.h"
  17. #include "cpp_api/s_internal.h"
  18. #include "inventorymanager.h"
  19. #include "lua_api/l_inventory.h"
  20. #include "lua_api/l_item.h"
  21. #include "log.h"
  22. // Return number of accepted items to be moved
  23. int ScriptApiDetached::detached_inventory_AllowMove(
  24. const MoveAction &ma, int count,
  25. ServerActiveObject *player)
  26. {
  27. SCRIPTAPI_PRECHECKHEADER
  28. int error_handler = PUSH_ERROR_HANDLER(L);
  29. // Push callback function on stack
  30. if (!getDetachedInventoryCallback(ma.from_inv.name, "allow_move"))
  31. return count;
  32. // function(inv, from_list, from_index, to_list, to_index, count, player)
  33. // inv
  34. InvRef::create(L, ma.from_inv);
  35. lua_pushstring(L, ma.from_list.c_str()); // from_list
  36. lua_pushinteger(L, ma.from_i + 1); // from_index
  37. lua_pushstring(L, ma.to_list.c_str()); // to_list
  38. lua_pushinteger(L, ma.to_i + 1); // to_index
  39. lua_pushinteger(L, count); // count
  40. objectrefGetOrCreate(L, player); // player
  41. PCALL_RES(lua_pcall(L, 7, 1, error_handler));
  42. if(!lua_isnumber(L, -1))
  43. throw LuaError("allow_move should return a number. name=" + ma.from_inv.name);
  44. int ret = luaL_checkinteger(L, -1);
  45. lua_pop(L, 2); // Pop integer and error handler
  46. return ret;
  47. }
  48. // Return number of accepted items to be put
  49. int ScriptApiDetached::detached_inventory_AllowPut(
  50. const MoveAction &ma, const ItemStack &stack,
  51. ServerActiveObject *player)
  52. {
  53. SCRIPTAPI_PRECHECKHEADER
  54. int error_handler = PUSH_ERROR_HANDLER(L);
  55. // Push callback function on stack
  56. if (!getDetachedInventoryCallback(ma.to_inv.name, "allow_put"))
  57. return stack.count; // All will be accepted
  58. // Call function(inv, listname, index, stack, player)
  59. InvRef::create(L, ma.to_inv); // inv
  60. lua_pushstring(L, ma.to_list.c_str()); // listname
  61. lua_pushinteger(L, ma.to_i + 1); // index
  62. LuaItemStack::create(L, stack); // stack
  63. objectrefGetOrCreate(L, player); // player
  64. PCALL_RES(lua_pcall(L, 5, 1, error_handler));
  65. if (!lua_isnumber(L, -1))
  66. throw LuaError("allow_put should return a number. name=" + ma.to_inv.name);
  67. int ret = luaL_checkinteger(L, -1);
  68. lua_pop(L, 2); // Pop integer and error handler
  69. return ret;
  70. }
  71. // Return number of accepted items to be taken
  72. int ScriptApiDetached::detached_inventory_AllowTake(
  73. const MoveAction &ma, const ItemStack &stack,
  74. ServerActiveObject *player)
  75. {
  76. SCRIPTAPI_PRECHECKHEADER
  77. int error_handler = PUSH_ERROR_HANDLER(L);
  78. // Push callback function on stack
  79. if (!getDetachedInventoryCallback(ma.from_inv.name, "allow_take"))
  80. return stack.count; // All will be accepted
  81. // Call function(inv, listname, index, stack, player)
  82. InvRef::create(L, ma.from_inv); // inv
  83. lua_pushstring(L, ma.from_list.c_str()); // listname
  84. lua_pushinteger(L, ma.from_i + 1); // index
  85. LuaItemStack::create(L, stack); // stack
  86. objectrefGetOrCreate(L, player); // player
  87. PCALL_RES(lua_pcall(L, 5, 1, error_handler));
  88. if (!lua_isnumber(L, -1))
  89. throw LuaError("allow_take should return a number. name=" + ma.from_inv.name);
  90. int ret = luaL_checkinteger(L, -1);
  91. lua_pop(L, 2); // Pop integer and error handler
  92. return ret;
  93. }
  94. // Report moved items
  95. void ScriptApiDetached::detached_inventory_OnMove(
  96. const MoveAction &ma, int count,
  97. ServerActiveObject *player)
  98. {
  99. SCRIPTAPI_PRECHECKHEADER
  100. int error_handler = PUSH_ERROR_HANDLER(L);
  101. // Push callback function on stack
  102. if (!getDetachedInventoryCallback(ma.from_inv.name, "on_move"))
  103. return;
  104. // function(inv, from_list, from_index, to_list, to_index, count, player)
  105. // inv
  106. InvRef::create(L, ma.from_inv);
  107. lua_pushstring(L, ma.from_list.c_str()); // from_list
  108. lua_pushinteger(L, ma.from_i + 1); // from_index
  109. lua_pushstring(L, ma.to_list.c_str()); // to_list
  110. lua_pushinteger(L, ma.to_i + 1); // to_index
  111. lua_pushinteger(L, count); // count
  112. objectrefGetOrCreate(L, player); // player
  113. PCALL_RES(lua_pcall(L, 7, 0, error_handler));
  114. lua_pop(L, 1); // Pop error handler
  115. }
  116. // Report put items
  117. void ScriptApiDetached::detached_inventory_OnPut(
  118. const MoveAction &ma, const ItemStack &stack,
  119. ServerActiveObject *player)
  120. {
  121. SCRIPTAPI_PRECHECKHEADER
  122. int error_handler = PUSH_ERROR_HANDLER(L);
  123. // Push callback function on stack
  124. if (!getDetachedInventoryCallback(ma.to_inv.name, "on_put"))
  125. return;
  126. // Call function(inv, listname, index, stack, player)
  127. // inv
  128. InvRef::create(L, ma.to_inv);
  129. lua_pushstring(L, ma.to_list.c_str()); // listname
  130. lua_pushinteger(L, ma.to_i + 1); // index
  131. LuaItemStack::create(L, stack); // stack
  132. objectrefGetOrCreate(L, player); // player
  133. PCALL_RES(lua_pcall(L, 5, 0, error_handler));
  134. lua_pop(L, 1); // Pop error handler
  135. }
  136. // Report taken items
  137. void ScriptApiDetached::detached_inventory_OnTake(
  138. const MoveAction &ma, const ItemStack &stack,
  139. ServerActiveObject *player)
  140. {
  141. SCRIPTAPI_PRECHECKHEADER
  142. int error_handler = PUSH_ERROR_HANDLER(L);
  143. // Push callback function on stack
  144. if (!getDetachedInventoryCallback(ma.from_inv.name, "on_take"))
  145. return;
  146. // Call function(inv, listname, index, stack, player)
  147. // inv
  148. InvRef::create(L, ma.from_inv);
  149. lua_pushstring(L, ma.from_list.c_str()); // listname
  150. lua_pushinteger(L, ma.from_i + 1); // index
  151. LuaItemStack::create(L, stack); // stack
  152. objectrefGetOrCreate(L, player); // player
  153. PCALL_RES(lua_pcall(L, 5, 0, error_handler));
  154. lua_pop(L, 1); // Pop error handler
  155. }
  156. // Retrieves core.detached_inventories[name][callbackname]
  157. // If that is nil or on error, return false and stack is unchanged
  158. // If that is a function, returns true and pushes the
  159. // function onto the stack
  160. bool ScriptApiDetached::getDetachedInventoryCallback(
  161. const std::string &name, const char *callbackname)
  162. {
  163. lua_State *L = getStack();
  164. lua_getglobal(L, "core");
  165. lua_getfield(L, -1, "detached_inventories");
  166. lua_remove(L, -2);
  167. luaL_checktype(L, -1, LUA_TTABLE);
  168. lua_getfield(L, -1, name.c_str());
  169. lua_remove(L, -2);
  170. // Should be a table
  171. if (lua_type(L, -1) != LUA_TTABLE) {
  172. errorstream<<"Detached inventory \""<<name<<"\" not defined"<<std::endl;
  173. lua_pop(L, 1);
  174. return false;
  175. }
  176. setOriginFromTable(-1);
  177. lua_getfield(L, -1, callbackname);
  178. lua_remove(L, -2);
  179. // Should be a function or nil
  180. if (lua_type(L, -1) == LUA_TFUNCTION) {
  181. return true;
  182. }
  183. if (lua_isnil(L, -1)) {
  184. lua_pop(L, 1);
  185. return false;
  186. }
  187. errorstream << "Detached inventory \"" << name << "\" callback \""
  188. << callbackname << "\" is not a function" << std::endl;
  189. lua_pop(L, 1);
  190. return false;
  191. }