3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "cpp_api/s_inventory.h"
21 #include "inventorymanager.h"
22 #include "lua_api/l_inventory.h"
23 #include "lua_api/l_item.h"
26 // Return number of accepted items to be moved
27 int ScriptApiDetached::detached_inventory_AllowMove(
28 const std::string &name,
29 const std::string &from_list, int from_index,
30 const std::string &to_list, int to_index,
31 int count, ServerActiveObject *player)
33 SCRIPTAPI_PRECHECKHEADER
35 // Push callback function on stack
36 if(!getDetachedInventoryCallback(name, "allow_move"))
39 // function(inv, from_list, from_index, to_list, to_index, count, player)
41 InventoryLocation loc;
42 loc.setDetached(name);
43 InvRef::create(L, loc);
45 lua_pushstring(L, from_list.c_str());
47 lua_pushinteger(L, from_index + 1);
49 lua_pushstring(L, to_list.c_str());
51 lua_pushinteger(L, to_index + 1);
53 lua_pushinteger(L, count);
55 objectrefGetOrCreate(player);
56 if(lua_pcall(L, 7, 1, 0))
57 scriptError("error: %s", lua_tostring(L, -1));
58 if(!lua_isnumber(L, -1))
59 throw LuaError(L, "allow_move should return a number");
60 return luaL_checkinteger(L, -1);
63 // Return number of accepted items to be put
64 int ScriptApiDetached::detached_inventory_AllowPut(
65 const std::string &name,
66 const std::string &listname, int index, ItemStack &stack,
67 ServerActiveObject *player)
69 SCRIPTAPI_PRECHECKHEADER
71 // Push callback function on stack
72 if(!getDetachedInventoryCallback(name, "allow_put"))
73 return stack.count; // All will be accepted
75 // Call function(inv, listname, index, stack, player)
77 InventoryLocation loc;
78 loc.setDetached(name);
79 InvRef::create(L, loc);
81 lua_pushstring(L, listname.c_str());
83 lua_pushinteger(L, index + 1);
85 LuaItemStack::create(L, stack);
87 objectrefGetOrCreate(player);
88 if(lua_pcall(L, 5, 1, 0))
89 scriptError("error: %s", lua_tostring(L, -1));
90 if(!lua_isnumber(L, -1))
91 throw LuaError(L, "allow_put should return a number");
92 return luaL_checkinteger(L, -1);
95 // Return number of accepted items to be taken
96 int ScriptApiDetached::detached_inventory_AllowTake(
97 const std::string &name,
98 const std::string &listname, int index, ItemStack &stack,
99 ServerActiveObject *player)
101 SCRIPTAPI_PRECHECKHEADER
103 // Push callback function on stack
104 if(!getDetachedInventoryCallback(name, "allow_take"))
105 return stack.count; // All will be accepted
107 // Call function(inv, listname, index, stack, player)
109 InventoryLocation loc;
110 loc.setDetached(name);
111 InvRef::create(L, loc);
113 lua_pushstring(L, listname.c_str());
115 lua_pushinteger(L, index + 1);
117 LuaItemStack::create(L, stack);
119 objectrefGetOrCreate(player);
120 if(lua_pcall(L, 5, 1, 0))
121 scriptError("error: %s", lua_tostring(L, -1));
122 if(!lua_isnumber(L, -1))
123 throw LuaError(L, "allow_take should return a number");
124 return luaL_checkinteger(L, -1);
127 // Report moved items
128 void ScriptApiDetached::detached_inventory_OnMove(
129 const std::string &name,
130 const std::string &from_list, int from_index,
131 const std::string &to_list, int to_index,
132 int count, ServerActiveObject *player)
134 SCRIPTAPI_PRECHECKHEADER
136 // Push callback function on stack
137 if(!getDetachedInventoryCallback(name, "on_move"))
140 // function(inv, from_list, from_index, to_list, to_index, count, player)
142 InventoryLocation loc;
143 loc.setDetached(name);
144 InvRef::create(L, loc);
146 lua_pushstring(L, from_list.c_str());
148 lua_pushinteger(L, from_index + 1);
150 lua_pushstring(L, to_list.c_str());
152 lua_pushinteger(L, to_index + 1);
154 lua_pushinteger(L, count);
156 objectrefGetOrCreate(player);
157 if(lua_pcall(L, 7, 0, 0))
158 scriptError("error: %s", lua_tostring(L, -1));
162 void ScriptApiDetached::detached_inventory_OnPut(
163 const std::string &name,
164 const std::string &listname, int index, ItemStack &stack,
165 ServerActiveObject *player)
167 SCRIPTAPI_PRECHECKHEADER
169 // Push callback function on stack
170 if(!getDetachedInventoryCallback(name, "on_put"))
173 // Call function(inv, listname, index, stack, player)
175 InventoryLocation loc;
176 loc.setDetached(name);
177 InvRef::create(L, loc);
179 lua_pushstring(L, listname.c_str());
181 lua_pushinteger(L, index + 1);
183 LuaItemStack::create(L, stack);
185 objectrefGetOrCreate(player);
186 if(lua_pcall(L, 5, 0, 0))
187 scriptError("error: %s", lua_tostring(L, -1));
190 // Report taken items
191 void ScriptApiDetached::detached_inventory_OnTake(
192 const std::string &name,
193 const std::string &listname, int index, ItemStack &stack,
194 ServerActiveObject *player)
196 SCRIPTAPI_PRECHECKHEADER
198 // Push callback function on stack
199 if(!getDetachedInventoryCallback(name, "on_take"))
202 // Call function(inv, listname, index, stack, player)
204 InventoryLocation loc;
205 loc.setDetached(name);
206 InvRef::create(L, loc);
208 lua_pushstring(L, listname.c_str());
210 lua_pushinteger(L, index + 1);
212 LuaItemStack::create(L, stack);
214 objectrefGetOrCreate(player);
215 if(lua_pcall(L, 5, 0, 0))
216 scriptError("error: %s", lua_tostring(L, -1));
219 // Retrieves minetest.detached_inventories[name][callbackname]
220 // If that is nil or on error, return false and stack is unchanged
221 // If that is a function, returns true and pushes the
222 // function onto the stack
223 bool ScriptApiDetached::getDetachedInventoryCallback(
224 const std::string &name, const char *callbackname)
226 lua_State *L = getStack();
228 lua_getglobal(L, "minetest");
229 lua_getfield(L, -1, "detached_inventories");
231 luaL_checktype(L, -1, LUA_TTABLE);
232 lua_getfield(L, -1, name.c_str());
235 if(lua_type(L, -1) != LUA_TTABLE)
237 errorstream<<"Item \""<<name<<"\" not defined"<<std::endl;
241 lua_getfield(L, -1, callbackname);
243 // Should be a function or nil
244 if(lua_type(L, -1) == LUA_TFUNCTION)
248 else if(lua_isnil(L, -1))
255 errorstream<<"Detached inventory \""<<name<<"\" callback \""
256 <<callbackname<<"\" is not a function"<<std::endl;