]> git.lizzy.rs Git - minetest.git/blob - src/script/lua_api/l_item.cpp
Add support for statbar “off state” icons (#9462)
[minetest.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 "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 // set_name(self, name)
61 int LuaItemStack::l_set_name(lua_State *L)
62 {
63         NO_MAP_LOCK_REQUIRED;
64         LuaItemStack *o = checkobject(L, 1);
65         ItemStack &item = o->m_stack;
66
67         bool status = true;
68         item.name = luaL_checkstring(L, 2);
69         if (item.name.empty() || item.empty()) {
70                 item.clear();
71                 status = false;
72         }
73
74         lua_pushboolean(L, status);
75         return 1;
76 }
77
78 // get_count(self) -> number
79 int LuaItemStack::l_get_count(lua_State *L)
80 {
81         NO_MAP_LOCK_REQUIRED;
82         LuaItemStack *o = checkobject(L, 1);
83         ItemStack &item = o->m_stack;
84         lua_pushinteger(L, item.count);
85         return 1;
86 }
87
88 // set_count(self, number)
89 int LuaItemStack::l_set_count(lua_State *L)
90 {
91         NO_MAP_LOCK_REQUIRED;
92         LuaItemStack *o = checkobject(L, 1);
93         ItemStack &item = o->m_stack;
94
95         bool status;
96         lua_Integer count = luaL_checkinteger(L, 2);
97         if (count > 0 && count <= 65535) {
98                 item.count = count;
99                 status = true;
100         } else {
101                 item.clear();
102                 status = false;
103         }
104
105         lua_pushboolean(L, status);
106         return 1;
107 }
108
109 // get_wear(self) -> number
110 int LuaItemStack::l_get_wear(lua_State *L)
111 {
112         NO_MAP_LOCK_REQUIRED;
113         LuaItemStack *o = checkobject(L, 1);
114         ItemStack &item = o->m_stack;
115         lua_pushinteger(L, item.wear);
116         return 1;
117 }
118
119 // set_wear(self, number)
120 int LuaItemStack::l_set_wear(lua_State *L)
121 {
122         NO_MAP_LOCK_REQUIRED;
123         LuaItemStack *o = checkobject(L, 1);
124         ItemStack &item = o->m_stack;
125
126         bool status;
127         lua_Integer wear = luaL_checkinteger(L, 2);
128         if (wear <= 65535) {
129                 item.wear = wear;
130                 status = true;
131         } else {
132                 item.clear();
133                 status = false;
134         }
135
136         lua_pushboolean(L, status);
137         return 1;
138 }
139
140 // get_meta(self) -> string
141 int LuaItemStack::l_get_meta(lua_State *L)
142 {
143         NO_MAP_LOCK_REQUIRED;
144         LuaItemStack *o = checkobject(L, 1);
145         ItemStackMetaRef::create(L, &o->m_stack);
146         return 1;
147 }
148
149 // DEPRECATED
150 // get_metadata(self) -> string
151 int LuaItemStack::l_get_metadata(lua_State *L)
152 {
153         NO_MAP_LOCK_REQUIRED;
154         LuaItemStack *o = checkobject(L, 1);
155         ItemStack &item = o->m_stack;
156         const std::string &value = item.metadata.getString("");
157         lua_pushlstring(L, value.c_str(), value.size());
158         return 1;
159 }
160
161 // DEPRECATED
162 // set_metadata(self, string)
163 int LuaItemStack::l_set_metadata(lua_State *L)
164 {
165         NO_MAP_LOCK_REQUIRED;
166         LuaItemStack *o = checkobject(L, 1);
167         ItemStack &item = o->m_stack;
168
169         size_t len = 0;
170         const char *ptr = luaL_checklstring(L, 2, &len);
171         item.metadata.setString("", std::string(ptr, len));
172
173         lua_pushboolean(L, true);
174         return 1;
175 }
176
177 // get_description(self)
178 int LuaItemStack::l_get_description(lua_State *L)
179 {
180         NO_MAP_LOCK_REQUIRED;
181         LuaItemStack *o = checkobject(L, 1);
182         std::string desc = o->m_stack.getDescription(getGameDef(L)->idef());
183         lua_pushstring(L, desc.c_str());
184         return 1;
185 }
186
187 // clear(self) -> true
188 int LuaItemStack::l_clear(lua_State *L)
189 {
190         NO_MAP_LOCK_REQUIRED;
191         LuaItemStack *o = checkobject(L, 1);
192         o->m_stack.clear();
193         lua_pushboolean(L, true);
194         return 1;
195 }
196
197 // replace(self, itemstack or itemstring or table or nil) -> true
198 int LuaItemStack::l_replace(lua_State *L)
199 {
200         NO_MAP_LOCK_REQUIRED;
201         LuaItemStack *o = checkobject(L, 1);
202         o->m_stack = read_item(L, 2, getGameDef(L)->idef());
203         lua_pushboolean(L, true);
204         return 1;
205 }
206
207 // to_string(self) -> string
208 int LuaItemStack::l_to_string(lua_State *L)
209 {
210         NO_MAP_LOCK_REQUIRED;
211         LuaItemStack *o = checkobject(L, 1);
212         std::string itemstring = o->m_stack.getItemString();
213         lua_pushstring(L, itemstring.c_str());
214         return 1;
215 }
216
217 // to_table(self) -> table or nil
218 int LuaItemStack::l_to_table(lua_State *L)
219 {
220         NO_MAP_LOCK_REQUIRED;
221         LuaItemStack *o = checkobject(L, 1);
222         const ItemStack &item = o->m_stack;
223         if(item.empty())
224         {
225                 lua_pushnil(L);
226         }
227         else
228         {
229                 lua_newtable(L);
230                 lua_pushstring(L, item.name.c_str());
231                 lua_setfield(L, -2, "name");
232                 lua_pushinteger(L, item.count);
233                 lua_setfield(L, -2, "count");
234                 lua_pushinteger(L, item.wear);
235                 lua_setfield(L, -2, "wear");
236
237                 const std::string &metadata_str = item.metadata.getString("");
238                 lua_pushlstring(L, metadata_str.c_str(), metadata_str.size());
239                 lua_setfield(L, -2, "metadata");
240
241                 lua_newtable(L);
242                 const StringMap &fields = item.metadata.getStrings();
243                 for (const auto &field : fields) {
244                         const std::string &name = field.first;
245                         if (name.empty())
246                                 continue;
247                         const std::string &value = field.second;
248                         lua_pushlstring(L, name.c_str(), name.size());
249                         lua_pushlstring(L, value.c_str(), value.size());
250                         lua_settable(L, -3);
251                 }
252                 lua_setfield(L, -2, "meta");
253         }
254         return 1;
255 }
256
257 // get_stack_max(self) -> number
258 int LuaItemStack::l_get_stack_max(lua_State *L)
259 {
260         NO_MAP_LOCK_REQUIRED;
261         LuaItemStack *o = checkobject(L, 1);
262         ItemStack &item = o->m_stack;
263         lua_pushinteger(L, item.getStackMax(getGameDef(L)->idef()));
264         return 1;
265 }
266
267 // get_free_space(self) -> number
268 int LuaItemStack::l_get_free_space(lua_State *L)
269 {
270         NO_MAP_LOCK_REQUIRED;
271         LuaItemStack *o = checkobject(L, 1);
272         ItemStack &item = o->m_stack;
273         lua_pushinteger(L, item.freeSpace(getGameDef(L)->idef()));
274         return 1;
275 }
276
277 // is_known(self) -> true/false
278 // Checks if the item is defined.
279 int LuaItemStack::l_is_known(lua_State *L)
280 {
281         NO_MAP_LOCK_REQUIRED;
282         LuaItemStack *o = checkobject(L, 1);
283         ItemStack &item = o->m_stack;
284         bool is_known = item.isKnown(getGameDef(L)->idef());
285         lua_pushboolean(L, is_known);
286         return 1;
287 }
288
289 // get_definition(self) -> table
290 // Returns the item definition table from registered_items,
291 // or a fallback one (name="unknown")
292 int LuaItemStack::l_get_definition(lua_State *L)
293 {
294         NO_MAP_LOCK_REQUIRED;
295         LuaItemStack *o = checkobject(L, 1);
296         ItemStack &item = o->m_stack;
297
298         // Get registered_items[name]
299         lua_getglobal(L, "core");
300         lua_getfield(L, -1, "registered_items");
301         luaL_checktype(L, -1, LUA_TTABLE);
302         lua_getfield(L, -1, item.name.c_str());
303         if(lua_isnil(L, -1))
304         {
305                 lua_pop(L, 1);
306                 lua_getfield(L, -1, "unknown");
307         }
308         return 1;
309 }
310
311 // get_tool_capabilities(self) -> table
312 // Returns the effective tool digging properties.
313 // Returns those of the hand ("") if this item has none associated.
314 int LuaItemStack::l_get_tool_capabilities(lua_State *L)
315 {
316         NO_MAP_LOCK_REQUIRED;
317         LuaItemStack *o = checkobject(L, 1);
318         ItemStack &item = o->m_stack;
319         const ToolCapabilities &prop =
320                 item.getToolCapabilities(getGameDef(L)->idef());
321         push_tool_capabilities(L, prop);
322         return 1;
323 }
324
325 // add_wear(self, amount) -> true/false
326 // The range for "amount" is [0,65535]. Wear is only added if the item
327 // is a tool. Adding wear might destroy the item.
328 // Returns true if the item is (or was) a tool.
329 int LuaItemStack::l_add_wear(lua_State *L)
330 {
331         NO_MAP_LOCK_REQUIRED;
332         LuaItemStack *o = checkobject(L, 1);
333         ItemStack &item = o->m_stack;
334         int amount = lua_tointeger(L, 2);
335         bool result = item.addWear(amount, getGameDef(L)->idef());
336         lua_pushboolean(L, result);
337         return 1;
338 }
339
340 // add_item(self, itemstack or itemstring or table or nil) -> itemstack
341 // Returns leftover item stack
342 int LuaItemStack::l_add_item(lua_State *L)
343 {
344         NO_MAP_LOCK_REQUIRED;
345         LuaItemStack *o = checkobject(L, 1);
346         ItemStack &item = o->m_stack;
347         ItemStack newitem = read_item(L, -1, getGameDef(L)->idef());
348         ItemStack leftover = item.addItem(newitem, getGameDef(L)->idef());
349         create(L, leftover);
350         return 1;
351 }
352
353 // item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack
354 // First return value is true iff the new item fits fully into the stack
355 // Second return value is the would-be-left-over item stack
356 int LuaItemStack::l_item_fits(lua_State *L)
357 {
358         NO_MAP_LOCK_REQUIRED;
359         LuaItemStack *o = checkobject(L, 1);
360         ItemStack &item = o->m_stack;
361         ItemStack newitem = read_item(L, 2, getGameDef(L)->idef());
362         ItemStack restitem;
363         bool fits = item.itemFits(newitem, &restitem, getGameDef(L)->idef());
364         lua_pushboolean(L, fits);  // first return value
365         create(L, restitem);       // second return value
366         return 2;
367 }
368
369 // take_item(self, takecount=1) -> itemstack
370 int LuaItemStack::l_take_item(lua_State *L)
371 {
372         NO_MAP_LOCK_REQUIRED;
373         LuaItemStack *o = checkobject(L, 1);
374         ItemStack &item = o->m_stack;
375         u32 takecount = 1;
376         if(!lua_isnone(L, 2))
377                 takecount = luaL_checkinteger(L, 2);
378         ItemStack taken = item.takeItem(takecount);
379         create(L, taken);
380         return 1;
381 }
382
383 // peek_item(self, peekcount=1) -> itemstack
384 int LuaItemStack::l_peek_item(lua_State *L)
385 {
386         NO_MAP_LOCK_REQUIRED;
387         LuaItemStack *o = checkobject(L, 1);
388         ItemStack &item = o->m_stack;
389         u32 peekcount = 1;
390         if(!lua_isnone(L, 2))
391                 peekcount = lua_tointeger(L, 2);
392         ItemStack peekaboo = item.peekItem(peekcount);
393         create(L, peekaboo);
394         return 1;
395 }
396
397 LuaItemStack::LuaItemStack(const ItemStack &item):
398         m_stack(item)
399 {
400 }
401
402 const ItemStack& LuaItemStack::getItem() const
403 {
404         return m_stack;
405 }
406 ItemStack& LuaItemStack::getItem()
407 {
408         return m_stack;
409 }
410
411 // LuaItemStack(itemstack or itemstring or table or nil)
412 // Creates an LuaItemStack and leaves it on top of stack
413 int LuaItemStack::create_object(lua_State *L)
414 {
415         NO_MAP_LOCK_REQUIRED;
416         ItemStack item;
417         if (!lua_isnone(L, 1))
418                 item = read_item(L, 1, getGameDef(L)->idef());
419         LuaItemStack *o = new LuaItemStack(item);
420         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
421         luaL_getmetatable(L, className);
422         lua_setmetatable(L, -2);
423         return 1;
424 }
425 // Not callable from Lua
426 int LuaItemStack::create(lua_State *L, const ItemStack &item)
427 {
428         NO_MAP_LOCK_REQUIRED;
429         LuaItemStack *o = new LuaItemStack(item);
430         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
431         luaL_getmetatable(L, className);
432         lua_setmetatable(L, -2);
433         return 1;
434 }
435
436 LuaItemStack* LuaItemStack::checkobject(lua_State *L, int narg)
437 {
438         luaL_checktype(L, narg, LUA_TUSERDATA);
439         void *ud = luaL_checkudata(L, narg, className);
440         if(!ud) luaL_typerror(L, narg, className);
441         return *(LuaItemStack**)ud;  // unbox pointer
442 }
443
444 void LuaItemStack::Register(lua_State *L)
445 {
446         lua_newtable(L);
447         int methodtable = lua_gettop(L);
448         luaL_newmetatable(L, className);
449         int metatable = lua_gettop(L);
450
451         lua_pushliteral(L, "__metatable");
452         lua_pushvalue(L, methodtable);
453         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
454
455         lua_pushliteral(L, "__index");
456         lua_pushvalue(L, methodtable);
457         lua_settable(L, metatable);
458
459         lua_pushliteral(L, "__gc");
460         lua_pushcfunction(L, gc_object);
461         lua_settable(L, metatable);
462
463         lua_pop(L, 1);  // drop metatable
464
465         luaL_openlib(L, 0, methods, 0);  // fill methodtable
466         lua_pop(L, 1);  // drop methodtable
467
468         // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil))
469         lua_register(L, className, create_object);
470 }
471
472 const char LuaItemStack::className[] = "ItemStack";
473 const luaL_Reg LuaItemStack::methods[] = {
474         luamethod(LuaItemStack, is_empty),
475         luamethod(LuaItemStack, get_name),
476         luamethod(LuaItemStack, set_name),
477         luamethod(LuaItemStack, get_count),
478         luamethod(LuaItemStack, set_count),
479         luamethod(LuaItemStack, get_wear),
480         luamethod(LuaItemStack, set_wear),
481         luamethod(LuaItemStack, get_meta),
482         luamethod(LuaItemStack, get_metadata),
483         luamethod(LuaItemStack, set_metadata),
484         luamethod(LuaItemStack, get_description),
485         luamethod(LuaItemStack, clear),
486         luamethod(LuaItemStack, replace),
487         luamethod(LuaItemStack, to_string),
488         luamethod(LuaItemStack, to_table),
489         luamethod(LuaItemStack, get_stack_max),
490         luamethod(LuaItemStack, get_free_space),
491         luamethod(LuaItemStack, is_known),
492         luamethod(LuaItemStack, get_definition),
493         luamethod(LuaItemStack, get_tool_capabilities),
494         luamethod(LuaItemStack, add_wear),
495         luamethod(LuaItemStack, add_item),
496         luamethod(LuaItemStack, item_fits),
497         luamethod(LuaItemStack, take_item),
498         luamethod(LuaItemStack, peek_item),
499         {0,0}
500 };
501
502 /*
503         ItemDefinition
504 */
505
506 // register_item_raw({lots of stuff})
507 int ModApiItemMod::l_register_item_raw(lua_State *L)
508 {
509         NO_MAP_LOCK_REQUIRED;
510         luaL_checktype(L, 1, LUA_TTABLE);
511         int table = 1;
512
513         // Get the writable item and node definition managers from the server
514         IWritableItemDefManager *idef =
515                         getServer(L)->getWritableItemDefManager();
516         NodeDefManager *ndef =
517                         getServer(L)->getWritableNodeDefManager();
518
519         // Check if name is defined
520         std::string name;
521         lua_getfield(L, table, "name");
522         if(lua_isstring(L, -1)){
523                 name = readParam<std::string>(L, -1);
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 IItemDefManager *idef = getGameDef(L)->getItemDefManager();
613         const NodeDefManager *ndef = getGameDef(L)->getNodeDefManager();
614
615         // If this is called at mod load time, NodeDefManager isn't aware of
616         // aliases yet, so we need to handle them manually
617         std::string alias_name = idef->getAlias(name);
618
619         content_t content_id;
620         if (alias_name != name) {
621                 if (!ndef->getId(alias_name, content_id))
622                         throw LuaError("Unknown node: " + alias_name +
623                                         " (from alias " + name + ")");
624         } else if (!ndef->getId(name, content_id)) {
625                 throw LuaError("Unknown node: " + name);
626         }
627
628         lua_pushinteger(L, content_id);
629         return 1; /* number of results */
630 }
631
632 // get_name_from_content_id(name)
633 int ModApiItemMod::l_get_name_from_content_id(lua_State *L)
634 {
635         NO_MAP_LOCK_REQUIRED;
636         content_t c = luaL_checkint(L, 1);
637
638         const NodeDefManager *ndef = getGameDef(L)->getNodeDefManager();
639         const char *name = ndef->get(c).name.c_str();
640
641         lua_pushstring(L, name);
642         return 1; /* number of results */
643 }
644
645 void ModApiItemMod::Initialize(lua_State *L, int top)
646 {
647         API_FCT(register_item_raw);
648         API_FCT(unregister_item_raw);
649         API_FCT(register_alias_raw);
650         API_FCT(get_content_id);
651         API_FCT(get_name_from_content_id);
652 }