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 "cpp_api/s_internal.h"
22 #include "inventorymanager.h"
23 #include "lua_api/l_inventory.h"
24 #include "lua_api/l_item.h"
27 // Return number of accepted items to be moved
28 int ScriptApiDetached::detached_inventory_AllowMove(
29 const std::string &name,
30 const std::string &from_list, int from_index,
31 const std::string &to_list, int to_index,
32 int count, ServerActiveObject *player)
34 SCRIPTAPI_PRECHECKHEADER
36 // Push callback function on stack
37 if(!getDetachedInventoryCallback(name, "allow_move"))
40 // function(inv, from_list, from_index, to_list, to_index, count, player)
42 InventoryLocation loc;
43 loc.setDetached(name);
44 InvRef::create(L, loc);
46 lua_pushstring(L, from_list.c_str());
48 lua_pushinteger(L, from_index + 1);
50 lua_pushstring(L, to_list.c_str());
52 lua_pushinteger(L, to_index + 1);
54 lua_pushinteger(L, count);
56 objectrefGetOrCreate(player);
57 if(lua_pcall(L, 7, 1, 0))
58 scriptError("error: %s", lua_tostring(L, -1));
59 if(!lua_isnumber(L, -1))
60 throw LuaError(L, "allow_move should return a number");
61 return luaL_checkinteger(L, -1);
64 // Return number of accepted items to be put
65 int ScriptApiDetached::detached_inventory_AllowPut(
66 const std::string &name,
67 const std::string &listname, int index, ItemStack &stack,
68 ServerActiveObject *player)
70 SCRIPTAPI_PRECHECKHEADER
72 // Push callback function on stack
73 if(!getDetachedInventoryCallback(name, "allow_put"))
74 return stack.count; // All will be accepted
76 // Call function(inv, listname, index, stack, player)
78 InventoryLocation loc;
79 loc.setDetached(name);
80 InvRef::create(L, loc);
82 lua_pushstring(L, listname.c_str());
84 lua_pushinteger(L, index + 1);
86 LuaItemStack::create(L, stack);
88 objectrefGetOrCreate(player);
89 if(lua_pcall(L, 5, 1, 0))
90 scriptError("error: %s", lua_tostring(L, -1));
91 if(!lua_isnumber(L, -1))
92 throw LuaError(L, "allow_put should return a number");
93 return luaL_checkinteger(L, -1);
96 // Return number of accepted items to be taken
97 int ScriptApiDetached::detached_inventory_AllowTake(
98 const std::string &name,
99 const std::string &listname, int index, ItemStack &stack,
100 ServerActiveObject *player)
102 SCRIPTAPI_PRECHECKHEADER
104 // Push callback function on stack
105 if(!getDetachedInventoryCallback(name, "allow_take"))
106 return stack.count; // All will be accepted
108 // Call function(inv, listname, index, stack, player)
110 InventoryLocation loc;
111 loc.setDetached(name);
112 InvRef::create(L, loc);
114 lua_pushstring(L, listname.c_str());
116 lua_pushinteger(L, index + 1);
118 LuaItemStack::create(L, stack);
120 objectrefGetOrCreate(player);
121 if(lua_pcall(L, 5, 1, 0))
122 scriptError("error: %s", lua_tostring(L, -1));
123 if(!lua_isnumber(L, -1))
124 throw LuaError(L, "allow_take should return a number");
125 return luaL_checkinteger(L, -1);
128 // Report moved items
129 void ScriptApiDetached::detached_inventory_OnMove(
130 const std::string &name,
131 const std::string &from_list, int from_index,
132 const std::string &to_list, int to_index,
133 int count, ServerActiveObject *player)
135 SCRIPTAPI_PRECHECKHEADER
137 // Push callback function on stack
138 if(!getDetachedInventoryCallback(name, "on_move"))
141 // function(inv, from_list, from_index, to_list, to_index, count, player)
143 InventoryLocation loc;
144 loc.setDetached(name);
145 InvRef::create(L, loc);
147 lua_pushstring(L, from_list.c_str());
149 lua_pushinteger(L, from_index + 1);
151 lua_pushstring(L, to_list.c_str());
153 lua_pushinteger(L, to_index + 1);
155 lua_pushinteger(L, count);
157 objectrefGetOrCreate(player);
158 if(lua_pcall(L, 7, 0, 0))
159 scriptError("error: %s", lua_tostring(L, -1));
163 void ScriptApiDetached::detached_inventory_OnPut(
164 const std::string &name,
165 const std::string &listname, int index, ItemStack &stack,
166 ServerActiveObject *player)
168 SCRIPTAPI_PRECHECKHEADER
170 // Push callback function on stack
171 if(!getDetachedInventoryCallback(name, "on_put"))
174 // Call function(inv, listname, index, stack, player)
176 InventoryLocation loc;
177 loc.setDetached(name);
178 InvRef::create(L, loc);
180 lua_pushstring(L, listname.c_str());
182 lua_pushinteger(L, index + 1);
184 LuaItemStack::create(L, stack);
186 objectrefGetOrCreate(player);
187 if(lua_pcall(L, 5, 0, 0))
188 scriptError("error: %s", lua_tostring(L, -1));
191 // Report taken items
192 void ScriptApiDetached::detached_inventory_OnTake(
193 const std::string &name,
194 const std::string &listname, int index, ItemStack &stack,
195 ServerActiveObject *player)
197 SCRIPTAPI_PRECHECKHEADER
199 // Push callback function on stack
200 if(!getDetachedInventoryCallback(name, "on_take"))
203 // Call function(inv, listname, index, stack, player)
205 InventoryLocation loc;
206 loc.setDetached(name);
207 InvRef::create(L, loc);
209 lua_pushstring(L, listname.c_str());
211 lua_pushinteger(L, index + 1);
213 LuaItemStack::create(L, stack);
215 objectrefGetOrCreate(player);
216 if(lua_pcall(L, 5, 0, 0))
217 scriptError("error: %s", lua_tostring(L, -1));
220 // Retrieves minetest.detached_inventories[name][callbackname]
221 // If that is nil or on error, return false and stack is unchanged
222 // If that is a function, returns true and pushes the
223 // function onto the stack
224 bool ScriptApiDetached::getDetachedInventoryCallback(
225 const std::string &name, const char *callbackname)
227 lua_State *L = getStack();
229 lua_getglobal(L, "minetest");
230 lua_getfield(L, -1, "detached_inventories");
232 luaL_checktype(L, -1, LUA_TTABLE);
233 lua_getfield(L, -1, name.c_str());
236 if(lua_type(L, -1) != LUA_TTABLE)
238 errorstream<<"Item \""<<name<<"\" not defined"<<std::endl;
242 lua_getfield(L, -1, callbackname);
244 // Should be a function or nil
245 if(lua_type(L, -1) == LUA_TFUNCTION)
249 else if(lua_isnil(L, -1))
256 errorstream<<"Detached inventory \""<<name<<"\" callback \""
257 <<callbackname<<"\" is not a function"<<std::endl;