]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_item.cpp
Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenu
[dragonfireclient.git] / src / script / lua_api / l_item.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 "lua_api/l_item.h"
21 #include "lua_api/l_internal.h"
22 #include "common/c_converter.h"
23 #include "common/c_content.h"
24 #include "itemdef.h"
25 #include "nodedef.h"
26 #include "server.h"
27 #include "content_sao.h"
28 #include "inventory.h"
29 #include "log.h"
30
31
32 // garbage collector
33 int LuaItemStack::gc_object(lua_State *L)
34 {
35         LuaItemStack *o = *(LuaItemStack **)(lua_touserdata(L, 1));
36         delete o;
37         return 0;
38 }
39
40 // is_empty(self) -> true/false
41 int LuaItemStack::l_is_empty(lua_State *L)
42 {
43         NO_MAP_LOCK_REQUIRED;
44         LuaItemStack *o = checkobject(L, 1);
45         ItemStack &item = o->m_stack;
46         lua_pushboolean(L, item.empty());
47         return 1;
48 }
49
50 // get_name(self) -> string
51 int LuaItemStack::l_get_name(lua_State *L)
52 {
53         NO_MAP_LOCK_REQUIRED;
54         LuaItemStack *o = checkobject(L, 1);
55         ItemStack &item = o->m_stack;
56         lua_pushstring(L, item.name.c_str());
57         return 1;
58 }
59
60 // get_count(self) -> number
61 int LuaItemStack::l_get_count(lua_State *L)
62 {
63         NO_MAP_LOCK_REQUIRED;
64         LuaItemStack *o = checkobject(L, 1);
65         ItemStack &item = o->m_stack;
66         lua_pushinteger(L, item.count);
67         return 1;
68 }
69
70 // get_wear(self) -> number
71 int LuaItemStack::l_get_wear(lua_State *L)
72 {
73         NO_MAP_LOCK_REQUIRED;
74         LuaItemStack *o = checkobject(L, 1);
75         ItemStack &item = o->m_stack;
76         lua_pushinteger(L, item.wear);
77         return 1;
78 }
79
80 // get_metadata(self) -> string
81 int LuaItemStack::l_get_metadata(lua_State *L)
82 {
83         NO_MAP_LOCK_REQUIRED;
84         LuaItemStack *o = checkobject(L, 1);
85         ItemStack &item = o->m_stack;
86         lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
87         return 1;
88 }
89
90 // clear(self) -> true
91 int LuaItemStack::l_clear(lua_State *L)
92 {
93         NO_MAP_LOCK_REQUIRED;
94         LuaItemStack *o = checkobject(L, 1);
95         o->m_stack.clear();
96         lua_pushboolean(L, true);
97         return 1;
98 }
99
100 // replace(self, itemstack or itemstring or table or nil) -> true
101 int LuaItemStack::l_replace(lua_State *L)
102 {
103         NO_MAP_LOCK_REQUIRED;
104         LuaItemStack *o = checkobject(L, 1);
105         o->m_stack = read_item(L,2,getServer(L));
106         lua_pushboolean(L, true);
107         return 1;
108 }
109
110 // to_string(self) -> string
111 int LuaItemStack::l_to_string(lua_State *L)
112 {
113         NO_MAP_LOCK_REQUIRED;
114         LuaItemStack *o = checkobject(L, 1);
115         std::string itemstring = o->m_stack.getItemString();
116         lua_pushstring(L, itemstring.c_str());
117         return 1;
118 }
119
120 // to_table(self) -> table or nil
121 int LuaItemStack::l_to_table(lua_State *L)
122 {
123         NO_MAP_LOCK_REQUIRED;
124         LuaItemStack *o = checkobject(L, 1);
125         const ItemStack &item = o->m_stack;
126         if(item.empty())
127         {
128                 lua_pushnil(L);
129         }
130         else
131         {
132                 lua_newtable(L);
133                 lua_pushstring(L, item.name.c_str());
134                 lua_setfield(L, -2, "name");
135                 lua_pushinteger(L, item.count);
136                 lua_setfield(L, -2, "count");
137                 lua_pushinteger(L, item.wear);
138                 lua_setfield(L, -2, "wear");
139                 lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
140                 lua_setfield(L, -2, "metadata");
141         }
142         return 1;
143 }
144
145 // get_stack_max(self) -> number
146 int LuaItemStack::l_get_stack_max(lua_State *L)
147 {
148         NO_MAP_LOCK_REQUIRED;
149         LuaItemStack *o = checkobject(L, 1);
150         ItemStack &item = o->m_stack;
151         lua_pushinteger(L, item.getStackMax(getServer(L)->idef()));
152         return 1;
153 }
154
155 // get_free_space(self) -> number
156 int LuaItemStack::l_get_free_space(lua_State *L)
157 {
158         NO_MAP_LOCK_REQUIRED;
159         LuaItemStack *o = checkobject(L, 1);
160         ItemStack &item = o->m_stack;
161         lua_pushinteger(L, item.freeSpace(getServer(L)->idef()));
162         return 1;
163 }
164
165 // is_known(self) -> true/false
166 // Checks if the item is defined.
167 int LuaItemStack::l_is_known(lua_State *L)
168 {
169         NO_MAP_LOCK_REQUIRED;
170         LuaItemStack *o = checkobject(L, 1);
171         ItemStack &item = o->m_stack;
172         bool is_known = item.isKnown(getServer(L)->idef());
173         lua_pushboolean(L, is_known);
174         return 1;
175 }
176
177 // get_definition(self) -> table
178 // Returns the item definition table from minetest.registered_items,
179 // or a fallback one (name="unknown")
180 int LuaItemStack::l_get_definition(lua_State *L)
181 {
182         NO_MAP_LOCK_REQUIRED;
183         LuaItemStack *o = checkobject(L, 1);
184         ItemStack &item = o->m_stack;
185
186         // Get minetest.registered_items[name]
187         lua_getglobal(L, "minetest");
188         lua_getfield(L, -1, "registered_items");
189         luaL_checktype(L, -1, LUA_TTABLE);
190         lua_getfield(L, -1, item.name.c_str());
191         if(lua_isnil(L, -1))
192         {
193                 lua_pop(L, 1);
194                 lua_getfield(L, -1, "unknown");
195         }
196         return 1;
197 }
198
199 // get_tool_capabilities(self) -> table
200 // Returns the effective tool digging properties.
201 // Returns those of the hand ("") if this item has none associated.
202 int LuaItemStack::l_get_tool_capabilities(lua_State *L)
203 {
204         NO_MAP_LOCK_REQUIRED;
205         LuaItemStack *o = checkobject(L, 1);
206         ItemStack &item = o->m_stack;
207         const ToolCapabilities &prop =
208                 item.getToolCapabilities(getServer(L)->idef());
209         push_tool_capabilities(L, prop);
210         return 1;
211 }
212
213 // add_wear(self, amount) -> true/false
214 // The range for "amount" is [0,65535]. Wear is only added if the item
215 // is a tool. Adding wear might destroy the item.
216 // Returns true if the item is (or was) a tool.
217 int LuaItemStack::l_add_wear(lua_State *L)
218 {
219         NO_MAP_LOCK_REQUIRED;
220         LuaItemStack *o = checkobject(L, 1);
221         ItemStack &item = o->m_stack;
222         int amount = lua_tointeger(L, 2);
223         bool result = item.addWear(amount, getServer(L)->idef());
224         lua_pushboolean(L, result);
225         return 1;
226 }
227
228 // add_item(self, itemstack or itemstring or table or nil) -> itemstack
229 // Returns leftover item stack
230 int LuaItemStack::l_add_item(lua_State *L)
231 {
232         NO_MAP_LOCK_REQUIRED;
233         LuaItemStack *o = checkobject(L, 1);
234         ItemStack &item = o->m_stack;
235         ItemStack newitem = read_item(L,-1, getServer(L));
236         ItemStack leftover = item.addItem(newitem, getServer(L)->idef());
237         create(L, leftover);
238         return 1;
239 }
240
241 // item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack
242 // First return value is true iff the new item fits fully into the stack
243 // Second return value is the would-be-left-over item stack
244 int LuaItemStack::l_item_fits(lua_State *L)
245 {
246         NO_MAP_LOCK_REQUIRED;
247         LuaItemStack *o = checkobject(L, 1);
248         ItemStack &item = o->m_stack;
249         ItemStack newitem = read_item(L, 2, getServer(L));
250         ItemStack restitem;
251         bool fits = item.itemFits(newitem, &restitem, getServer(L)->idef());
252         lua_pushboolean(L, fits);  // first return value
253         create(L, restitem);       // second return value
254         return 2;
255 }
256
257 // take_item(self, takecount=1) -> itemstack
258 int LuaItemStack::l_take_item(lua_State *L)
259 {
260         NO_MAP_LOCK_REQUIRED;
261         LuaItemStack *o = checkobject(L, 1);
262         ItemStack &item = o->m_stack;
263         u32 takecount = 1;
264         if(!lua_isnone(L, 2))
265                 takecount = luaL_checkinteger(L, 2);
266         ItemStack taken = item.takeItem(takecount);
267         create(L, taken);
268         return 1;
269 }
270
271 // peek_item(self, peekcount=1) -> itemstack
272 int LuaItemStack::l_peek_item(lua_State *L)
273 {
274         NO_MAP_LOCK_REQUIRED;
275         LuaItemStack *o = checkobject(L, 1);
276         ItemStack &item = o->m_stack;
277         u32 peekcount = 1;
278         if(!lua_isnone(L, 2))
279                 peekcount = lua_tointeger(L, 2);
280         ItemStack peekaboo = item.peekItem(peekcount);
281         create(L, peekaboo);
282         return 1;
283 }
284
285 LuaItemStack::LuaItemStack(const ItemStack &item):
286         m_stack(item)
287 {
288 }
289
290 LuaItemStack::~LuaItemStack()
291 {
292 }
293
294 const ItemStack& LuaItemStack::getItem() const
295 {
296         return m_stack;
297 }
298 ItemStack& LuaItemStack::getItem()
299 {
300         return m_stack;
301 }
302
303 // LuaItemStack(itemstack or itemstring or table or nil)
304 // Creates an LuaItemStack and leaves it on top of stack
305 int LuaItemStack::create_object(lua_State *L)
306 {
307         NO_MAP_LOCK_REQUIRED;
308         ItemStack item = read_item(L, 1, getServer(L));
309         LuaItemStack *o = new LuaItemStack(item);
310         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
311         luaL_getmetatable(L, className);
312         lua_setmetatable(L, -2);
313         return 1;
314 }
315 // Not callable from Lua
316 int LuaItemStack::create(lua_State *L, const ItemStack &item)
317 {
318         NO_MAP_LOCK_REQUIRED;
319         LuaItemStack *o = new LuaItemStack(item);
320         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
321         luaL_getmetatable(L, className);
322         lua_setmetatable(L, -2);
323         return 1;
324 }
325
326 LuaItemStack* LuaItemStack::checkobject(lua_State *L, int narg)
327 {
328         luaL_checktype(L, narg, LUA_TUSERDATA);
329         void *ud = luaL_checkudata(L, narg, className);
330         if(!ud) luaL_typerror(L, narg, className);
331         return *(LuaItemStack**)ud;  // unbox pointer
332 }
333
334 void LuaItemStack::Register(lua_State *L)
335 {
336         lua_newtable(L);
337         int methodtable = lua_gettop(L);
338         luaL_newmetatable(L, className);
339         int metatable = lua_gettop(L);
340
341         lua_pushliteral(L, "__metatable");
342         lua_pushvalue(L, methodtable);
343         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
344
345         lua_pushliteral(L, "__index");
346         lua_pushvalue(L, methodtable);
347         lua_settable(L, metatable);
348
349         lua_pushliteral(L, "__gc");
350         lua_pushcfunction(L, gc_object);
351         lua_settable(L, metatable);
352
353         lua_pop(L, 1);  // drop metatable
354
355         luaL_openlib(L, 0, methods, 0);  // fill methodtable
356         lua_pop(L, 1);  // drop methodtable
357
358         // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil))
359         lua_register(L, className, create_object);
360 }
361
362 const char LuaItemStack::className[] = "ItemStack";
363 const luaL_reg LuaItemStack::methods[] = {
364         luamethod(LuaItemStack, is_empty),
365         luamethod(LuaItemStack, get_name),
366         luamethod(LuaItemStack, get_count),
367         luamethod(LuaItemStack, get_wear),
368         luamethod(LuaItemStack, get_metadata),
369         luamethod(LuaItemStack, clear),
370         luamethod(LuaItemStack, replace),
371         luamethod(LuaItemStack, to_string),
372         luamethod(LuaItemStack, to_table),
373         luamethod(LuaItemStack, get_stack_max),
374         luamethod(LuaItemStack, get_free_space),
375         luamethod(LuaItemStack, is_known),
376         luamethod(LuaItemStack, get_definition),
377         luamethod(LuaItemStack, get_tool_capabilities),
378         luamethod(LuaItemStack, add_wear),
379         luamethod(LuaItemStack, add_item),
380         luamethod(LuaItemStack, item_fits),
381         luamethod(LuaItemStack, take_item),
382         luamethod(LuaItemStack, peek_item),
383         {0,0}
384 };
385
386 /*
387         ItemDefinition
388 */
389
390 // register_item_raw({lots of stuff})
391 int ModApiItemMod::l_register_item_raw(lua_State *L)
392 {
393         NO_MAP_LOCK_REQUIRED;
394         luaL_checktype(L, 1, LUA_TTABLE);
395         int table = 1;
396
397         // Get the writable item and node definition managers from the server
398         IWritableItemDefManager *idef =
399                         getServer(L)->getWritableItemDefManager();
400         IWritableNodeDefManager *ndef =
401                         getServer(L)->getWritableNodeDefManager();
402
403         // Check if name is defined
404         std::string name;
405         lua_getfield(L, table, "name");
406         if(lua_isstring(L, -1)){
407                 name = lua_tostring(L, -1);
408                 verbosestream<<"register_item_raw: "<<name<<std::endl;
409         } else {
410                 throw LuaError(L, "register_item_raw: name is not defined or not a string");
411         }
412
413         // Check if on_use is defined
414
415         ItemDefinition def;
416         // Set a distinctive default value to check if this is set
417         def.node_placement_prediction = "__default";
418
419         // Read the item definition
420         def = read_item_definition(L, table, def);
421
422         // Default to having client-side placement prediction for nodes
423         // ("" in item definition sets it off)
424         if(def.node_placement_prediction == "__default"){
425                 if(def.type == ITEM_NODE)
426                         def.node_placement_prediction = name;
427                 else
428                         def.node_placement_prediction = "";
429         }
430
431         // Register item definition
432         idef->registerItem(def);
433
434         // Read the node definition (content features) and register it
435         if(def.type == ITEM_NODE){
436                 ContentFeatures f = read_content_features(L, table);
437                 content_t id = ndef->set(f.name, f);
438
439                 if(id > MAX_REGISTERED_CONTENT){
440                         throw LuaError(L, "Number of registerable nodes ("
441                                         + itos(MAX_REGISTERED_CONTENT+1)
442                                         + ") exceeded (" + name + ")");
443                 }
444         }
445
446         return 0; /* number of results */
447 }
448
449 // register_alias_raw(name, convert_to_name)
450 int ModApiItemMod::l_register_alias_raw(lua_State *L)
451 {
452         NO_MAP_LOCK_REQUIRED;
453         std::string name = luaL_checkstring(L, 1);
454         std::string convert_to = luaL_checkstring(L, 2);
455
456         // Get the writable item definition manager from the server
457         IWritableItemDefManager *idef =
458                         getServer(L)->getWritableItemDefManager();
459
460         idef->registerAlias(name, convert_to);
461
462         return 0; /* number of results */
463 }
464
465 // get_content_id(name)
466 int ModApiItemMod::l_get_content_id(lua_State *L)
467 {
468         NO_MAP_LOCK_REQUIRED;
469         std::string name = luaL_checkstring(L, 1);
470
471         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
472         content_t c = ndef->getId(name);
473         
474         lua_pushinteger(L, c);
475         return 1; /* number of results */
476 }
477
478 // get_name_from_content_id(name)
479 int ModApiItemMod::l_get_name_from_content_id(lua_State *L)
480 {
481         NO_MAP_LOCK_REQUIRED;
482         content_t c = luaL_checkint(L, 1);
483
484         INodeDefManager *ndef = getServer(L)->getNodeDefManager();
485         const char *name = ndef->get(c).name.c_str();
486         
487         lua_pushstring(L, name);
488         return 1; /* number of results */
489 }
490
491 void ModApiItemMod::Initialize(lua_State *L, int top)
492 {
493         API_FCT(register_item_raw);
494         API_FCT(register_alias_raw);
495         API_FCT(get_content_id);
496         API_FCT(get_name_from_content_id);
497 }