]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/cpp_api/s_inventory.cpp
Improve Script CPP API diagnostics
[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         lua_pushstring(L, from_list.c_str()); // from_list
46         lua_pushinteger(L, from_index + 1);   // from_index
47         lua_pushstring(L, to_list.c_str());   // to_list
48         lua_pushinteger(L, to_index + 1);     // to_index
49         lua_pushinteger(L, count);            // count
50         objectrefGetOrCreate(L, player);      // player
51         PCALL_RES(lua_pcall(L, 7, 1, m_errorhandler));
52         if(!lua_isnumber(L, -1))
53                 throw LuaError("allow_move should return a number. name=" + name);
54         int ret = luaL_checkinteger(L, -1);
55         lua_pop(L, 1); // Pop integer
56         return ret;
57 }
58
59 // Return number of accepted items to be put
60 int ScriptApiDetached::detached_inventory_AllowPut(
61                 const std::string &name,
62                 const std::string &listname, int index, ItemStack &stack,
63                 ServerActiveObject *player)
64 {
65         SCRIPTAPI_PRECHECKHEADER
66
67         // Push callback function on stack
68         if (!getDetachedInventoryCallback(name, "allow_put"))
69                 return stack.count; // All will be accepted
70
71         // Call function(inv, listname, index, stack, player)
72         InventoryLocation loc;
73         loc.setDetached(name);
74         InvRef::create(L, loc);              // inv
75         lua_pushstring(L, listname.c_str()); // listname
76         lua_pushinteger(L, index + 1);       // index
77         LuaItemStack::create(L, stack);      // stack
78         objectrefGetOrCreate(L, player);     // player
79         PCALL_RES(lua_pcall(L, 5, 1, m_errorhandler));
80         if (!lua_isnumber(L, -1))
81                 throw LuaError("allow_put should return a number. name=" + name);
82         int ret = luaL_checkinteger(L, -1);
83         lua_pop(L, 1); // Pop integer
84         return ret;
85 }
86
87 // Return number of accepted items to be taken
88 int ScriptApiDetached::detached_inventory_AllowTake(
89                 const std::string &name,
90                 const std::string &listname, int index, ItemStack &stack,
91                 ServerActiveObject *player)
92 {
93         SCRIPTAPI_PRECHECKHEADER
94
95         // Push callback function on stack
96         if (!getDetachedInventoryCallback(name, "allow_take"))
97                 return stack.count; // All will be accepted
98
99         // Call function(inv, listname, index, stack, player)
100         InventoryLocation loc;
101         loc.setDetached(name);
102         InvRef::create(L, loc);              // inv
103         lua_pushstring(L, listname.c_str()); // listname
104         lua_pushinteger(L, index + 1);       // index
105         LuaItemStack::create(L, stack);      // stack
106         objectrefGetOrCreate(L, player);     // player
107         PCALL_RES(lua_pcall(L, 5, 1, m_errorhandler));
108         if (!lua_isnumber(L, -1))
109                 throw LuaError("allow_take should return a number. name=" + name);
110         int ret = luaL_checkinteger(L, -1);
111         lua_pop(L, 1); // Pop integer
112         return ret;
113 }
114
115 // Report moved items
116 void ScriptApiDetached::detached_inventory_OnMove(
117                 const std::string &name,
118                 const std::string &from_list, int from_index,
119                 const std::string &to_list, int to_index,
120                 int count, ServerActiveObject *player)
121 {
122         SCRIPTAPI_PRECHECKHEADER
123
124         // Push callback function on stack
125         if (!getDetachedInventoryCallback(name, "on_move"))
126                 return;
127
128         // function(inv, from_list, from_index, to_list, to_index, count, player)
129         // inv
130         InventoryLocation loc;
131         loc.setDetached(name);
132         InvRef::create(L, loc);
133         lua_pushstring(L, from_list.c_str()); // from_list
134         lua_pushinteger(L, from_index + 1);   // from_index
135         lua_pushstring(L, to_list.c_str());   // to_list
136         lua_pushinteger(L, to_index + 1);     // to_index
137         lua_pushinteger(L, count);            // count
138         objectrefGetOrCreate(L, player);      // player
139         PCALL_RES(lua_pcall(L, 7, 0, m_errorhandler));
140 }
141
142 // Report put items
143 void ScriptApiDetached::detached_inventory_OnPut(
144                 const std::string &name,
145                 const std::string &listname, int index, ItemStack &stack,
146                 ServerActiveObject *player)
147 {
148         SCRIPTAPI_PRECHECKHEADER
149
150         // Push callback function on stack
151         if (!getDetachedInventoryCallback(name, "on_put"))
152                 return;
153
154         // Call function(inv, listname, index, stack, player)
155         // inv
156         InventoryLocation loc;
157         loc.setDetached(name);
158         InvRef::create(L, loc);
159         lua_pushstring(L, listname.c_str()); // listname
160         lua_pushinteger(L, index + 1);       // index
161         LuaItemStack::create(L, stack);      // stack
162         objectrefGetOrCreate(L, player);     // player
163         PCALL_RES(lua_pcall(L, 5, 0, m_errorhandler));
164 }
165
166 // Report taken items
167 void ScriptApiDetached::detached_inventory_OnTake(
168                 const std::string &name,
169                 const std::string &listname, int index, ItemStack &stack,
170                 ServerActiveObject *player)
171 {
172         SCRIPTAPI_PRECHECKHEADER
173
174         // Push callback function on stack
175         if (!getDetachedInventoryCallback(name, "on_take"))
176                 return;
177
178         // Call function(inv, listname, index, stack, player)
179         // inv
180         InventoryLocation loc;
181         loc.setDetached(name);
182         InvRef::create(L, loc);
183         lua_pushstring(L, listname.c_str()); // listname
184         lua_pushinteger(L, index + 1);       // index
185         LuaItemStack::create(L, stack);      // stack
186         objectrefGetOrCreate(L, player);     // player
187         PCALL_RES(lua_pcall(L, 5, 0, m_errorhandler));
188 }
189
190 // Retrieves core.detached_inventories[name][callbackname]
191 // If that is nil or on error, return false and stack is unchanged
192 // If that is a function, returns true and pushes the
193 // function onto the stack
194 bool ScriptApiDetached::getDetachedInventoryCallback(
195                 const std::string &name, const char *callbackname)
196 {
197         lua_State *L = getStack();
198
199         lua_getglobal(L, "core");
200         lua_getfield(L, -1, "detached_inventories");
201         lua_remove(L, -2);
202         luaL_checktype(L, -1, LUA_TTABLE);
203         lua_getfield(L, -1, name.c_str());
204         lua_remove(L, -2);
205         // Should be a table
206         if(lua_type(L, -1) != LUA_TTABLE)
207         {
208                 errorstream<<"Detached inventory \""<<name<<"\" not defined"<<std::endl;
209                 lua_pop(L, 1);
210                 return false;
211         }
212         lua_getfield(L, -1, callbackname);
213         lua_remove(L, -2);
214         // Should be a function or nil
215         if(lua_type(L, -1) == LUA_TFUNCTION)
216         {
217                 return true;
218         }
219         else if(lua_isnil(L, -1))
220         {
221                 lua_pop(L, 1);
222                 return false;
223         }
224         else
225         {
226                 errorstream<<"Detached inventory \""<<name<<"\" callback \""
227                         <<callbackname<<"\" is not a function"<<std::endl;
228                 lua_pop(L, 1);
229                 return false;
230         }
231 }