]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_item.cpp
Add ItemStack:get_description() to get tooltip (#8847)
[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_itemstackmeta.h"
22 #include "lua_api/l_internal.h"
23 #include "common/c_converter.h"
24 #include "common/c_content.h"
25 #include "itemdef.h"
26 #include "nodedef.h"
27 #include "server.h"
28 #include "content_sao.h"
29 #include "inventory.h"
30 #include "log.h"
31
32
33 // garbage collector
34 int LuaItemStack::gc_object(lua_State *L)
35 {
36         LuaItemStack *o = *(LuaItemStack **)(lua_touserdata(L, 1));
37         delete o;
38         return 0;
39 }
40
41 // is_empty(self) -> true/false
42 int LuaItemStack::l_is_empty(lua_State *L)
43 {
44         NO_MAP_LOCK_REQUIRED;
45         LuaItemStack *o = checkobject(L, 1);
46         ItemStack &item = o->m_stack;
47         lua_pushboolean(L, item.empty());
48         return 1;
49 }
50
51 // get_name(self) -> string
52 int LuaItemStack::l_get_name(lua_State *L)
53 {
54         NO_MAP_LOCK_REQUIRED;
55         LuaItemStack *o = checkobject(L, 1);
56         ItemStack &item = o->m_stack;
57         lua_pushstring(L, item.name.c_str());
58         return 1;
59 }
60
61 // set_name(self, name)
62 int LuaItemStack::l_set_name(lua_State *L)
63 {
64         NO_MAP_LOCK_REQUIRED;
65         LuaItemStack *o = checkobject(L, 1);
66         ItemStack &item = o->m_stack;
67
68         bool status = true;
69         item.name = luaL_checkstring(L, 2);
70         if (item.name.empty() || item.empty()) {
71                 item.clear();
72                 status = false;
73         }
74
75         lua_pushboolean(L, status);
76         return 1;
77 }
78
79 // get_count(self) -> number
80 int LuaItemStack::l_get_count(lua_State *L)
81 {
82         NO_MAP_LOCK_REQUIRED;
83         LuaItemStack *o = checkobject(L, 1);
84         ItemStack &item = o->m_stack;
85         lua_pushinteger(L, item.count);
86         return 1;
87 }
88
89 // set_count(self, number)
90 int LuaItemStack::l_set_count(lua_State *L)
91 {
92         NO_MAP_LOCK_REQUIRED;
93         LuaItemStack *o = checkobject(L, 1);
94         ItemStack &item = o->m_stack;
95
96         bool status;
97         lua_Integer count = luaL_checkinteger(L, 2);
98         if (count > 0 && count <= 65535) {
99                 item.count = count;
100                 status = true;
101         } else {
102                 item.clear();
103                 status = false;
104         }
105
106         lua_pushboolean(L, status);
107         return 1;
108 }
109
110 // get_wear(self) -> number
111 int LuaItemStack::l_get_wear(lua_State *L)
112 {
113         NO_MAP_LOCK_REQUIRED;
114         LuaItemStack *o = checkobject(L, 1);
115         ItemStack &item = o->m_stack;
116         lua_pushinteger(L, item.wear);
117         return 1;
118 }
119
120 // set_wear(self, number)
121 int LuaItemStack::l_set_wear(lua_State *L)
122 {
123         NO_MAP_LOCK_REQUIRED;
124         LuaItemStack *o = checkobject(L, 1);
125         ItemStack &item = o->m_stack;
126
127         bool status;
128         lua_Integer wear = luaL_checkinteger(L, 2);
129         if (wear <= 65535) {
130                 item.wear = wear;
131                 status = true;
132         } else {
133                 item.clear();
134                 status = false;
135         }
136
137         lua_pushboolean(L, status);
138         return 1;
139 }
140
141 // get_meta(self) -> string
142 int LuaItemStack::l_get_meta(lua_State *L)
143 {
144         NO_MAP_LOCK_REQUIRED;
145         LuaItemStack *o = checkobject(L, 1);
146         ItemStackMetaRef::create(L, &o->m_stack);
147         return 1;
148 }
149
150 // DEPRECATED
151 // get_metadata(self) -> string
152 int LuaItemStack::l_get_metadata(lua_State *L)
153 {
154         NO_MAP_LOCK_REQUIRED;
155         LuaItemStack *o = checkobject(L, 1);
156         ItemStack &item = o->m_stack;
157         const std::string &value = item.metadata.getString("");
158         lua_pushlstring(L, value.c_str(), value.size());
159         return 1;
160 }
161
162 // DEPRECATED
163 // set_metadata(self, string)
164 int LuaItemStack::l_set_metadata(lua_State *L)
165 {
166         NO_MAP_LOCK_REQUIRED;
167         LuaItemStack *o = checkobject(L, 1);
168         ItemStack &item = o->m_stack;
169
170         size_t len = 0;
171         const char *ptr = luaL_checklstring(L, 2, &len);
172         item.metadata.setString("", std::string(ptr, len));
173
174         lua_pushboolean(L, true);
175         return 1;
176 }
177
178 // get_description(self)
179 int LuaItemStack::l_get_description(lua_State *L)
180 {
181         NO_MAP_LOCK_REQUIRED;
182         LuaItemStack *o = checkobject(L, 1);
183         std::string desc = o->m_stack.getDescription(getGameDef(L)->idef());
184         lua_pushstring(L, desc.c_str());
185         return 1;
186 }
187
188 // clear(self) -> true
189 int LuaItemStack::l_clear(lua_State *L)
190 {
191         NO_MAP_LOCK_REQUIRED;
192         LuaItemStack *o = checkobject(L, 1);
193         o->m_stack.clear();
194         lua_pushboolean(L, true);
195         return 1;
196 }
197
198 // replace(self, itemstack or itemstring or table or nil) -> true
199 int LuaItemStack::l_replace(lua_State *L)
200 {
201         NO_MAP_LOCK_REQUIRED;
202         LuaItemStack *o = checkobject(L, 1);
203         o->m_stack = read_item(L, 2, getGameDef(L)->idef());
204         lua_pushboolean(L, true);
205         return 1;
206 }
207
208 // to_string(self) -> string
209 int LuaItemStack::l_to_string(lua_State *L)
210 {
211         NO_MAP_LOCK_REQUIRED;
212         LuaItemStack *o = checkobject(L, 1);
213         std::string itemstring = o->m_stack.getItemString();
214         lua_pushstring(L, itemstring.c_str());
215         return 1;
216 }
217
218 // to_table(self) -> table or nil
219 int LuaItemStack::l_to_table(lua_State *L)
220 {
221         NO_MAP_LOCK_REQUIRED;
222         LuaItemStack *o = checkobject(L, 1);
223         const ItemStack &item = o->m_stack;
224         if(item.empty())
225         {
226                 lua_pushnil(L);
227         }
228         else
229         {
230                 lua_newtable(L);
231                 lua_pushstring(L, item.name.c_str());
232                 lua_setfield(L, -2, "name");
233                 lua_pushinteger(L, item.count);
234                 lua_setfield(L, -2, "count");
235                 lua_pushinteger(L, item.wear);
236                 lua_setfield(L, -2, "wear");
237
238                 const std::string &metadata_str = item.metadata.getString("");
239                 lua_pushlstring(L, metadata_str.c_str(), metadata_str.size());
240                 lua_setfield(L, -2, "metadata");
241
242                 lua_newtable(L);
243                 const StringMap &fields = item.metadata.getStrings();
244                 for (const auto &field : fields) {
245                         const std::string &name = field.first;
246                         if (name.empty())
247                                 continue;
248                         const std::string &value = field.second;
249                         lua_pushlstring(L, name.c_str(), name.size());
250                         lua_pushlstring(L, value.c_str(), value.size());
251                         lua_settable(L, -3);
252                 }
253                 lua_setfield(L, -2, "meta");
254         }
255         return 1;
256 }
257
258 // get_stack_max(self) -> number
259 int LuaItemStack::l_get_stack_max(lua_State *L)
260 {
261         NO_MAP_LOCK_REQUIRED;
262         LuaItemStack *o = checkobject(L, 1);
263         ItemStack &item = o->m_stack;
264         lua_pushinteger(L, item.getStackMax(getGameDef(L)->idef()));
265         return 1;
266 }
267
268 // get_free_space(self) -> number
269 int LuaItemStack::l_get_free_space(lua_State *L)
270 {
271         NO_MAP_LOCK_REQUIRED;
272         LuaItemStack *o = checkobject(L, 1);
273         ItemStack &item = o->m_stack;
274         lua_pushinteger(L, item.freeSpace(getGameDef(L)->idef()));
275         return 1;
276 }
277
278 // is_known(self) -> true/false
279 // Checks if the item is defined.
280 int LuaItemStack::l_is_known(lua_State *L)
281 {
282         NO_MAP_LOCK_REQUIRED;
283         LuaItemStack *o = checkobject(L, 1);
284         ItemStack &item = o->m_stack;
285         bool is_known = item.isKnown(getGameDef(L)->idef());
286         lua_pushboolean(L, is_known);
287         return 1;
288 }
289
290 // get_definition(self) -> table
291 // Returns the item definition table from registered_items,
292 // or a fallback one (name="unknown")
293 int LuaItemStack::l_get_definition(lua_State *L)
294 {
295         NO_MAP_LOCK_REQUIRED;
296         LuaItemStack *o = checkobject(L, 1);
297         ItemStack &item = o->m_stack;
298
299         // Get registered_items[name]
300         lua_getglobal(L, "core");
301         lua_getfield(L, -1, "registered_items");
302         luaL_checktype(L, -1, LUA_TTABLE);
303         lua_getfield(L, -1, item.name.c_str());
304         if(lua_isnil(L, -1))
305         {
306                 lua_pop(L, 1);
307                 lua_getfield(L, -1, "unknown");
308         }
309         return 1;
310 }
311
312 // get_tool_capabilities(self) -> table
313 // Returns the effective tool digging properties.
314 // Returns those of the hand ("") if this item has none associated.
315 int LuaItemStack::l_get_tool_capabilities(lua_State *L)
316 {
317         NO_MAP_LOCK_REQUIRED;
318         LuaItemStack *o = checkobject(L, 1);
319         ItemStack &item = o->m_stack;
320         const ToolCapabilities &prop =
321                 item.getToolCapabilities(getGameDef(L)->idef());
322         push_tool_capabilities(L, prop);
323         return 1;
324 }
325
326 // add_wear(self, amount) -> true/false
327 // The range for "amount" is [0,65535]. Wear is only added if the item
328 // is a tool. Adding wear might destroy the item.
329 // Returns true if the item is (or was) a tool.
330 int LuaItemStack::l_add_wear(lua_State *L)
331 {
332         NO_MAP_LOCK_REQUIRED;
333         LuaItemStack *o = checkobject(L, 1);
334         ItemStack &item = o->m_stack;
335         int amount = lua_tointeger(L, 2);
336         bool result = item.addWear(amount, getGameDef(L)->idef());
337         lua_pushboolean(L, result);
338         return 1;
339 }
340
341 // add_item(self, itemstack or itemstring or table or nil) -> itemstack
342 // Returns leftover item stack
343 int LuaItemStack::l_add_item(lua_State *L)
344 {
345         NO_MAP_LOCK_REQUIRED;
346         LuaItemStack *o = checkobject(L, 1);
347         ItemStack &item = o->m_stack;
348         ItemStack newitem = read_item(L, -1, getGameDef(L)->idef());
349         ItemStack leftover = item.addItem(newitem, getGameDef(L)->idef());
350         create(L, leftover);
351         return 1;
352 }
353
354 // item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack
355 // First return value is true iff the new item fits fully into the stack
356 // Second return value is the would-be-left-over item stack
357 int LuaItemStack::l_item_fits(lua_State *L)
358 {
359         NO_MAP_LOCK_REQUIRED;
360         LuaItemStack *o = checkobject(L, 1);
361         ItemStack &item = o->m_stack;
362         ItemStack newitem = read_item(L, 2, getGameDef(L)->idef());
363         ItemStack restitem;
364         bool fits = item.itemFits(newitem, &restitem, getGameDef(L)->idef());
365         lua_pushboolean(L, fits);  // first return value
366         create(L, restitem);       // second return value
367         return 2;
368 }
369
370 // take_item(self, takecount=1) -> itemstack
371 int LuaItemStack::l_take_item(lua_State *L)
372 {
373         NO_MAP_LOCK_REQUIRED;
374         LuaItemStack *o = checkobject(L, 1);
375         ItemStack &item = o->m_stack;
376         u32 takecount = 1;
377         if(!lua_isnone(L, 2))
378                 takecount = luaL_checkinteger(L, 2);
379         ItemStack taken = item.takeItem(takecount);
380         create(L, taken);
381         return 1;
382 }
383
384 // peek_item(self, peekcount=1) -> itemstack
385 int LuaItemStack::l_peek_item(lua_State *L)
386 {
387         NO_MAP_LOCK_REQUIRED;
388         LuaItemStack *o = checkobject(L, 1);
389         ItemStack &item = o->m_stack;
390         u32 peekcount = 1;
391         if(!lua_isnone(L, 2))
392                 peekcount = lua_tointeger(L, 2);
393         ItemStack peekaboo = item.peekItem(peekcount);
394         create(L, peekaboo);
395         return 1;
396 }
397
398 LuaItemStack::LuaItemStack(const ItemStack &item):
399         m_stack(item)
400 {
401 }
402
403 const ItemStack& LuaItemStack::getItem() const
404 {
405         return m_stack;
406 }
407 ItemStack& LuaItemStack::getItem()
408 {
409         return m_stack;
410 }
411
412 // LuaItemStack(itemstack or itemstring or table or nil)
413 // Creates an LuaItemStack and leaves it on top of stack
414 int LuaItemStack::create_object(lua_State *L)
415 {
416         NO_MAP_LOCK_REQUIRED;
417         ItemStack item = read_item(L, 1, getGameDef(L)->idef());
418         LuaItemStack *o = new LuaItemStack(item);
419         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
420         luaL_getmetatable(L, className);
421         lua_setmetatable(L, -2);
422         return 1;
423 }
424 // Not callable from Lua
425 int LuaItemStack::create(lua_State *L, const ItemStack &item)
426 {
427         NO_MAP_LOCK_REQUIRED;
428         LuaItemStack *o = new LuaItemStack(item);
429         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
430         luaL_getmetatable(L, className);
431         lua_setmetatable(L, -2);
432         return 1;
433 }
434
435 LuaItemStack* LuaItemStack::checkobject(lua_State *L, int narg)
436 {
437         luaL_checktype(L, narg, LUA_TUSERDATA);
438         void *ud = luaL_checkudata(L, narg, className);
439         if(!ud) luaL_typerror(L, narg, className);
440         return *(LuaItemStack**)ud;  // unbox pointer
441 }
442
443 void LuaItemStack::Register(lua_State *L)
444 {
445         lua_newtable(L);
446         int methodtable = lua_gettop(L);
447         luaL_newmetatable(L, className);
448         int metatable = lua_gettop(L);
449
450         lua_pushliteral(L, "__metatable");
451         lua_pushvalue(L, methodtable);
452         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
453
454         lua_pushliteral(L, "__index");
455         lua_pushvalue(L, methodtable);
456         lua_settable(L, metatable);
457
458         lua_pushliteral(L, "__gc");
459         lua_pushcfunction(L, gc_object);
460         lua_settable(L, metatable);
461
462         lua_pop(L, 1);  // drop metatable
463
464         luaL_openlib(L, 0, methods, 0);  // fill methodtable
465         lua_pop(L, 1);  // drop methodtable
466
467         // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil))
468         lua_register(L, className, create_object);
469 }
470
471 const char LuaItemStack::className[] = "ItemStack";
472 const luaL_Reg LuaItemStack::methods[] = {
473         luamethod(LuaItemStack, is_empty),
474         luamethod(LuaItemStack, get_name),
475         luamethod(LuaItemStack, set_name),
476         luamethod(LuaItemStack, get_count),
477         luamethod(LuaItemStack, set_count),
478         luamethod(LuaItemStack, get_wear),
479         luamethod(LuaItemStack, set_wear),
480         luamethod(LuaItemStack, get_meta),
481         luamethod(LuaItemStack, get_metadata),
482         luamethod(LuaItemStack, set_metadata),
483         luamethod(LuaItemStack, get_description),
484         luamethod(LuaItemStack, clear),
485         luamethod(LuaItemStack, replace),
486         luamethod(LuaItemStack, to_string),
487         luamethod(LuaItemStack, to_table),
488         luamethod(LuaItemStack, get_stack_max),
489         luamethod(LuaItemStack, get_free_space),
490         luamethod(LuaItemStack, is_known),
491         luamethod(LuaItemStack, get_definition),
492         luamethod(LuaItemStack, get_tool_capabilities),
493         luamethod(LuaItemStack, add_wear),
494         luamethod(LuaItemStack, add_item),
495         luamethod(LuaItemStack, item_fits),
496         luamethod(LuaItemStack, take_item),
497         luamethod(LuaItemStack, peek_item),
498         {0,0}
499 };
500
501 /*
502         ItemDefinition
503 */
504
505 // register_item_raw({lots of stuff})
506 int ModApiItemMod::l_register_item_raw(lua_State *L)
507 {
508         NO_MAP_LOCK_REQUIRED;
509         luaL_checktype(L, 1, LUA_TTABLE);
510         int table = 1;
511
512         // Get the writable item and node definition managers from the server
513         IWritableItemDefManager *idef =
514                         getServer(L)->getWritableItemDefManager();
515         NodeDefManager *ndef =
516                         getServer(L)->getWritableNodeDefManager();
517
518         // Check if name is defined
519         std::string name;
520         lua_getfield(L, table, "name");
521         if(lua_isstring(L, -1)){
522                 name = readParam<std::string>(L, -1);
523                 verbosestream<<"register_item_raw: "<<name<<std::endl;
524         } else {
525                 throw LuaError("register_item_raw: name is not defined or not a string");
526         }
527
528         // Check if on_use is defined
529
530         ItemDefinition def;
531         // Set a distinctive default value to check if this is set
532         def.node_placement_prediction = "__default";
533
534         // Read the item definition
535         read_item_definition(L, table, def, def);
536
537         // Default to having client-side placement prediction for nodes
538         // ("" in item definition sets it off)
539         if(def.node_placement_prediction == "__default"){
540                 if(def.type == ITEM_NODE)
541                         def.node_placement_prediction = name;
542                 else
543                         def.node_placement_prediction = "";
544         }
545
546         // Register item definition
547         idef->registerItem(def);
548
549         // Read the node definition (content features) and register it
550         if (def.type == ITEM_NODE) {
551                 ContentFeatures f = read_content_features(L, table);
552                 // when a mod reregisters ignore, only texture changes and such should
553                 // be done
554                 if (f.name == "ignore")
555                         return 0;
556
557                 content_t id = ndef->set(f.name, f);
558
559                 if (id > MAX_REGISTERED_CONTENT) {
560                         throw LuaError("Number of registerable nodes ("
561                                         + itos(MAX_REGISTERED_CONTENT+1)
562                                         + ") exceeded (" + name + ")");
563                 }
564         }
565
566         return 0; /* number of results */
567 }
568
569 // unregister_item(name)
570 int ModApiItemMod::l_unregister_item_raw(lua_State *L)
571 {
572         NO_MAP_LOCK_REQUIRED;
573         std::string name = luaL_checkstring(L, 1);
574
575         IWritableItemDefManager *idef =
576                         getServer(L)->getWritableItemDefManager();
577
578         // Unregister the node
579         if (idef->get(name).type == ITEM_NODE) {
580                 NodeDefManager *ndef =
581                         getServer(L)->getWritableNodeDefManager();
582                 ndef->removeNode(name);
583         }
584
585         idef->unregisterItem(name);
586
587         return 0; /* number of results */
588 }
589
590 // register_alias_raw(name, convert_to_name)
591 int ModApiItemMod::l_register_alias_raw(lua_State *L)
592 {
593         NO_MAP_LOCK_REQUIRED;
594         std::string name = luaL_checkstring(L, 1);
595         std::string convert_to = luaL_checkstring(L, 2);
596
597         // Get the writable item definition manager from the server
598         IWritableItemDefManager *idef =
599                         getServer(L)->getWritableItemDefManager();
600
601         idef->registerAlias(name, convert_to);
602
603         return 0; /* number of results */
604 }
605
606 // get_content_id(name)
607 int ModApiItemMod::l_get_content_id(lua_State *L)
608 {
609         NO_MAP_LOCK_REQUIRED;
610         std::string name = luaL_checkstring(L, 1);
611
612         const NodeDefManager *ndef = getGameDef(L)->getNodeDefManager();
613         content_t c = ndef->getId(name);
614
615         lua_pushinteger(L, c);
616         return 1; /* number of results */
617 }
618
619 // get_name_from_content_id(name)
620 int ModApiItemMod::l_get_name_from_content_id(lua_State *L)
621 {
622         NO_MAP_LOCK_REQUIRED;
623         content_t c = luaL_checkint(L, 1);
624
625         const NodeDefManager *ndef = getGameDef(L)->getNodeDefManager();
626         const char *name = ndef->get(c).name.c_str();
627
628         lua_pushstring(L, name);
629         return 1; /* number of results */
630 }
631
632 void ModApiItemMod::Initialize(lua_State *L, int top)
633 {
634         API_FCT(register_item_raw);
635         API_FCT(unregister_item_raw);
636         API_FCT(register_alias_raw);
637         API_FCT(get_content_id);
638         API_FCT(get_name_from_content_id);
639 }