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