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