]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/cpp_api/s_inventory.cpp
Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenu
[dragonfireclient.git] / src / script / cpp_api / s_inventory.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
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"
25 #include "log.h"
26
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)
33 {
34         SCRIPTAPI_PRECHECKHEADER
35
36         // Push callback function on stack
37         if(!getDetachedInventoryCallback(name, "allow_move"))
38                 return count;
39
40         // function(inv, from_list, from_index, to_list, to_index, count, player)
41         // inv
42         InventoryLocation loc;
43         loc.setDetached(name);
44         InvRef::create(L, loc);
45         // from_list
46         lua_pushstring(L, from_list.c_str());
47         // from_index
48         lua_pushinteger(L, from_index + 1);
49         // to_list
50         lua_pushstring(L, to_list.c_str());
51         // to_index
52         lua_pushinteger(L, to_index + 1);
53         // count
54         lua_pushinteger(L, count);
55         // player
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);
62 }
63
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)
69 {
70         SCRIPTAPI_PRECHECKHEADER
71
72         // Push callback function on stack
73         if(!getDetachedInventoryCallback(name, "allow_put"))
74                 return stack.count; // All will be accepted
75
76         // Call function(inv, listname, index, stack, player)
77         // inv
78         InventoryLocation loc;
79         loc.setDetached(name);
80         InvRef::create(L, loc);
81         // listname
82         lua_pushstring(L, listname.c_str());
83         // index
84         lua_pushinteger(L, index + 1);
85         // stack
86         LuaItemStack::create(L, stack);
87         // player
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);
94 }
95
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)
101 {
102         SCRIPTAPI_PRECHECKHEADER
103
104         // Push callback function on stack
105         if(!getDetachedInventoryCallback(name, "allow_take"))
106                 return stack.count; // All will be accepted
107
108         // Call function(inv, listname, index, stack, player)
109         // inv
110         InventoryLocation loc;
111         loc.setDetached(name);
112         InvRef::create(L, loc);
113         // listname
114         lua_pushstring(L, listname.c_str());
115         // index
116         lua_pushinteger(L, index + 1);
117         // stack
118         LuaItemStack::create(L, stack);
119         // player
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);
126 }
127
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)
134 {
135         SCRIPTAPI_PRECHECKHEADER
136
137         // Push callback function on stack
138         if(!getDetachedInventoryCallback(name, "on_move"))
139                 return;
140
141         // function(inv, from_list, from_index, to_list, to_index, count, player)
142         // inv
143         InventoryLocation loc;
144         loc.setDetached(name);
145         InvRef::create(L, loc);
146         // from_list
147         lua_pushstring(L, from_list.c_str());
148         // from_index
149         lua_pushinteger(L, from_index + 1);
150         // to_list
151         lua_pushstring(L, to_list.c_str());
152         // to_index
153         lua_pushinteger(L, to_index + 1);
154         // count
155         lua_pushinteger(L, count);
156         // player
157         objectrefGetOrCreate(player);
158         if(lua_pcall(L, 7, 0, 0))
159                 scriptError("error: %s", lua_tostring(L, -1));
160 }
161
162 // Report put items
163 void ScriptApiDetached::detached_inventory_OnPut(
164                 const std::string &name,
165                 const std::string &listname, int index, ItemStack &stack,
166                 ServerActiveObject *player)
167 {
168         SCRIPTAPI_PRECHECKHEADER
169
170         // Push callback function on stack
171         if(!getDetachedInventoryCallback(name, "on_put"))
172                 return;
173
174         // Call function(inv, listname, index, stack, player)
175         // inv
176         InventoryLocation loc;
177         loc.setDetached(name);
178         InvRef::create(L, loc);
179         // listname
180         lua_pushstring(L, listname.c_str());
181         // index
182         lua_pushinteger(L, index + 1);
183         // stack
184         LuaItemStack::create(L, stack);
185         // player
186         objectrefGetOrCreate(player);
187         if(lua_pcall(L, 5, 0, 0))
188                 scriptError("error: %s", lua_tostring(L, -1));
189 }
190
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)
196 {
197         SCRIPTAPI_PRECHECKHEADER
198
199         // Push callback function on stack
200         if(!getDetachedInventoryCallback(name, "on_take"))
201                 return;
202
203         // Call function(inv, listname, index, stack, player)
204         // inv
205         InventoryLocation loc;
206         loc.setDetached(name);
207         InvRef::create(L, loc);
208         // listname
209         lua_pushstring(L, listname.c_str());
210         // index
211         lua_pushinteger(L, index + 1);
212         // stack
213         LuaItemStack::create(L, stack);
214         // player
215         objectrefGetOrCreate(player);
216         if(lua_pcall(L, 5, 0, 0))
217                 scriptError("error: %s", lua_tostring(L, -1));
218 }
219
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)
226 {
227         lua_State *L = getStack();
228
229         lua_getglobal(L, "minetest");
230         lua_getfield(L, -1, "detached_inventories");
231         lua_remove(L, -2);
232         luaL_checktype(L, -1, LUA_TTABLE);
233         lua_getfield(L, -1, name.c_str());
234         lua_remove(L, -2);
235         // Should be a table
236         if(lua_type(L, -1) != LUA_TTABLE)
237         {
238                 errorstream<<"Item \""<<name<<"\" not defined"<<std::endl;
239                 lua_pop(L, 1);
240                 return false;
241         }
242         lua_getfield(L, -1, callbackname);
243         lua_remove(L, -2);
244         // Should be a function or nil
245         if(lua_type(L, -1) == LUA_TFUNCTION)
246         {
247                 return true;
248         }
249         else if(lua_isnil(L, -1))
250         {
251                 lua_pop(L, 1);
252                 return false;
253         }
254         else
255         {
256                 errorstream<<"Detached inventory \""<<name<<"\" callback \""
257                         <<callbackname<<"\" is not a function"<<std::endl;
258                 lua_pop(L, 1);
259                 return false;
260         }
261 }