]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_item.cpp
6182c037b848c7b15dcbe56c59d58bcc4d5dd0e8
[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 "common/c_converter.h"
22 #include "common/c_content.h"
23 #include "cpp_api/scriptapi.h"
24 #include "server.h"
25 #include "common/c_internal.h"
26
27 // garbage collector
28 int LuaItemStack::gc_object(lua_State *L)
29 {
30         LuaItemStack *o = *(LuaItemStack **)(lua_touserdata(L, 1));
31         delete o;
32         return 0;
33 }
34
35 // is_empty(self) -> true/false
36 int LuaItemStack::l_is_empty(lua_State *L)
37 {
38         NO_MAP_LOCK_REQUIRED;
39         LuaItemStack *o = checkobject(L, 1);
40         ItemStack &item = o->m_stack;
41         lua_pushboolean(L, item.empty());
42         return 1;
43 }
44
45 // get_name(self) -> string
46 int LuaItemStack::l_get_name(lua_State *L)
47 {
48         NO_MAP_LOCK_REQUIRED;
49         LuaItemStack *o = checkobject(L, 1);
50         ItemStack &item = o->m_stack;
51         lua_pushstring(L, item.name.c_str());
52         return 1;
53 }
54
55 // get_count(self) -> number
56 int LuaItemStack::l_get_count(lua_State *L)
57 {
58         NO_MAP_LOCK_REQUIRED;
59         LuaItemStack *o = checkobject(L, 1);
60         ItemStack &item = o->m_stack;
61         lua_pushinteger(L, item.count);
62         return 1;
63 }
64
65 // get_wear(self) -> number
66 int LuaItemStack::l_get_wear(lua_State *L)
67 {
68         NO_MAP_LOCK_REQUIRED;
69         LuaItemStack *o = checkobject(L, 1);
70         ItemStack &item = o->m_stack;
71         lua_pushinteger(L, item.wear);
72         return 1;
73 }
74
75 // get_metadata(self) -> string
76 int LuaItemStack::l_get_metadata(lua_State *L)
77 {
78         NO_MAP_LOCK_REQUIRED;
79         LuaItemStack *o = checkobject(L, 1);
80         ItemStack &item = o->m_stack;
81         lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
82         return 1;
83 }
84
85 // clear(self) -> true
86 int LuaItemStack::l_clear(lua_State *L)
87 {
88         NO_MAP_LOCK_REQUIRED;
89         LuaItemStack *o = checkobject(L, 1);
90         o->m_stack.clear();
91         lua_pushboolean(L, true);
92         return 1;
93 }
94
95 // replace(self, itemstack or itemstring or table or nil) -> true
96 int LuaItemStack::l_replace(lua_State *L)
97 {
98         NO_MAP_LOCK_REQUIRED;
99         LuaItemStack *o = checkobject(L, 1);
100         o->m_stack = read_item(L,2,STACK_TO_SERVER(L));
101         lua_pushboolean(L, true);
102         return 1;
103 }
104
105 // to_string(self) -> string
106 int LuaItemStack::l_to_string(lua_State *L)
107 {
108         NO_MAP_LOCK_REQUIRED;
109         LuaItemStack *o = checkobject(L, 1);
110         std::string itemstring = o->m_stack.getItemString();
111         lua_pushstring(L, itemstring.c_str());
112         return 1;
113 }
114
115 // to_table(self) -> table or nil
116 int LuaItemStack::l_to_table(lua_State *L)
117 {
118         NO_MAP_LOCK_REQUIRED;
119         LuaItemStack *o = checkobject(L, 1);
120         const ItemStack &item = o->m_stack;
121         if(item.empty())
122         {
123                 lua_pushnil(L);
124         }
125         else
126         {
127                 lua_newtable(L);
128                 lua_pushstring(L, item.name.c_str());
129                 lua_setfield(L, -2, "name");
130                 lua_pushinteger(L, item.count);
131                 lua_setfield(L, -2, "count");
132                 lua_pushinteger(L, item.wear);
133                 lua_setfield(L, -2, "wear");
134                 lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
135                 lua_setfield(L, -2, "metadata");
136         }
137         return 1;
138 }
139
140 // get_stack_max(self) -> number
141 int LuaItemStack::l_get_stack_max(lua_State *L)
142 {
143         NO_MAP_LOCK_REQUIRED;
144         LuaItemStack *o = checkobject(L, 1);
145         ItemStack &item = o->m_stack;
146         lua_pushinteger(L, item.getStackMax(STACK_TO_SERVER(L)->idef()));
147         return 1;
148 }
149
150 // get_free_space(self) -> number
151 int LuaItemStack::l_get_free_space(lua_State *L)
152 {
153         NO_MAP_LOCK_REQUIRED;
154         LuaItemStack *o = checkobject(L, 1);
155         ItemStack &item = o->m_stack;
156         lua_pushinteger(L, item.freeSpace(STACK_TO_SERVER(L)->idef()));
157         return 1;
158 }
159
160 // is_known(self) -> true/false
161 // Checks if the item is defined.
162 int LuaItemStack::l_is_known(lua_State *L)
163 {
164         NO_MAP_LOCK_REQUIRED;
165         LuaItemStack *o = checkobject(L, 1);
166         ItemStack &item = o->m_stack;
167         bool is_known = item.isKnown(STACK_TO_SERVER(L)->idef());
168         lua_pushboolean(L, is_known);
169         return 1;
170 }
171
172 // get_definition(self) -> table
173 // Returns the item definition table from minetest.registered_items,
174 // or a fallback one (name="unknown")
175 int LuaItemStack::l_get_definition(lua_State *L)
176 {
177         NO_MAP_LOCK_REQUIRED;
178         LuaItemStack *o = checkobject(L, 1);
179         ItemStack &item = o->m_stack;
180
181         // Get minetest.registered_items[name]
182         lua_getglobal(L, "minetest");
183         lua_getfield(L, -1, "registered_items");
184         luaL_checktype(L, -1, LUA_TTABLE);
185         lua_getfield(L, -1, item.name.c_str());
186         if(lua_isnil(L, -1))
187         {
188                 lua_pop(L, 1);
189                 lua_getfield(L, -1, "unknown");
190         }
191         return 1;
192 }
193
194 // get_tool_capabilities(self) -> table
195 // Returns the effective tool digging properties.
196 // Returns those of the hand ("") if this item has none associated.
197 int LuaItemStack::l_get_tool_capabilities(lua_State *L)
198 {
199         NO_MAP_LOCK_REQUIRED;
200         LuaItemStack *o = checkobject(L, 1);
201         ItemStack &item = o->m_stack;
202         const ToolCapabilities &prop =
203                 item.getToolCapabilities(STACK_TO_SERVER(L)->idef());
204         push_tool_capabilities(L, prop);
205         return 1;
206 }
207
208 // add_wear(self, amount) -> true/false
209 // The range for "amount" is [0,65535]. Wear is only added if the item
210 // is a tool. Adding wear might destroy the item.
211 // Returns true if the item is (or was) a tool.
212 int LuaItemStack::l_add_wear(lua_State *L)
213 {
214         NO_MAP_LOCK_REQUIRED;
215         LuaItemStack *o = checkobject(L, 1);
216         ItemStack &item = o->m_stack;
217         int amount = lua_tointeger(L, 2);
218         bool result = item.addWear(amount, STACK_TO_SERVER(L)->idef());
219         lua_pushboolean(L, result);
220         return 1;
221 }
222
223 // add_item(self, itemstack or itemstring or table or nil) -> itemstack
224 // Returns leftover item stack
225 int LuaItemStack::l_add_item(lua_State *L)
226 {
227         NO_MAP_LOCK_REQUIRED;
228         LuaItemStack *o = checkobject(L, 1);
229         ItemStack &item = o->m_stack;
230         ItemStack newitem = read_item(L,-1, STACK_TO_SERVER(L));
231         ItemStack leftover = item.addItem(newitem, STACK_TO_SERVER(L)->idef());
232         create(L, leftover);
233         return 1;
234 }
235
236 // item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack
237 // First return value is true iff the new item fits fully into the stack
238 // Second return value is the would-be-left-over item stack
239 int LuaItemStack::l_item_fits(lua_State *L)
240 {
241         NO_MAP_LOCK_REQUIRED;
242         LuaItemStack *o = checkobject(L, 1);
243         ItemStack &item = o->m_stack;
244         ItemStack newitem = read_item(L, 2 ,STACK_TO_SERVER(L));
245         ItemStack restitem;
246         bool fits = item.itemFits(newitem, &restitem, STACK_TO_SERVER(L)->idef());
247         lua_pushboolean(L, fits);  // first return value
248         create(L, restitem);       // second return value
249         return 2;
250 }
251
252 // take_item(self, takecount=1) -> itemstack
253 int LuaItemStack::l_take_item(lua_State *L)
254 {
255         NO_MAP_LOCK_REQUIRED;
256         LuaItemStack *o = checkobject(L, 1);
257         ItemStack &item = o->m_stack;
258         u32 takecount = 1;
259         if(!lua_isnone(L, 2))
260                 takecount = luaL_checkinteger(L, 2);
261         ItemStack taken = item.takeItem(takecount);
262         create(L, taken);
263         return 1;
264 }
265
266 // peek_item(self, peekcount=1) -> itemstack
267 int LuaItemStack::l_peek_item(lua_State *L)
268 {
269         NO_MAP_LOCK_REQUIRED;
270         LuaItemStack *o = checkobject(L, 1);
271         ItemStack &item = o->m_stack;
272         u32 peekcount = 1;
273         if(!lua_isnone(L, 2))
274                 peekcount = lua_tointeger(L, 2);
275         ItemStack peekaboo = item.peekItem(peekcount);
276         create(L, peekaboo);
277         return 1;
278 }
279
280 LuaItemStack::LuaItemStack(const ItemStack &item):
281         m_stack(item)
282 {
283 }
284
285 LuaItemStack::~LuaItemStack()
286 {
287 }
288
289 const ItemStack& LuaItemStack::getItem() const
290 {
291         return m_stack;
292 }
293 ItemStack& LuaItemStack::getItem()
294 {
295         return m_stack;
296 }
297
298 // LuaItemStack(itemstack or itemstring or table or nil)
299 // Creates an LuaItemStack and leaves it on top of stack
300 int LuaItemStack::create_object(lua_State *L)
301 {
302         NO_MAP_LOCK_REQUIRED;
303         ItemStack item = read_item(L,1,STACK_TO_SERVER(L));
304         LuaItemStack *o = new LuaItemStack(item);
305         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
306         luaL_getmetatable(L, className);
307         lua_setmetatable(L, -2);
308         return 1;
309 }
310 // Not callable from Lua
311 int LuaItemStack::create(lua_State *L, const ItemStack &item)
312 {
313         NO_MAP_LOCK_REQUIRED;
314         LuaItemStack *o = new LuaItemStack(item);
315         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
316         luaL_getmetatable(L, className);
317         lua_setmetatable(L, -2);
318         return 1;
319 }
320
321 LuaItemStack* LuaItemStack::checkobject(lua_State *L, int narg)
322 {
323         luaL_checktype(L, narg, LUA_TUSERDATA);
324         void *ud = luaL_checkudata(L, narg, className);
325         if(!ud) luaL_typerror(L, narg, className);
326         return *(LuaItemStack**)ud;  // unbox pointer
327 }
328
329 void LuaItemStack::Register(lua_State *L)
330 {
331         lua_newtable(L);
332         int methodtable = lua_gettop(L);
333         luaL_newmetatable(L, className);
334         int metatable = lua_gettop(L);
335
336         lua_pushliteral(L, "__metatable");
337         lua_pushvalue(L, methodtable);
338         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
339
340         lua_pushliteral(L, "__index");
341         lua_pushvalue(L, methodtable);
342         lua_settable(L, metatable);
343
344         lua_pushliteral(L, "__gc");
345         lua_pushcfunction(L, gc_object);
346         lua_settable(L, metatable);
347
348         lua_pop(L, 1);  // drop metatable
349
350         luaL_openlib(L, 0, methods, 0);  // fill methodtable
351         lua_pop(L, 1);  // drop methodtable
352
353         // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil))
354         lua_register(L, className, create_object);
355 }
356
357 const char LuaItemStack::className[] = "ItemStack";
358 const luaL_reg LuaItemStack::methods[] = {
359         luamethod(LuaItemStack, is_empty),
360         luamethod(LuaItemStack, get_name),
361         luamethod(LuaItemStack, get_count),
362         luamethod(LuaItemStack, get_wear),
363         luamethod(LuaItemStack, get_metadata),
364         luamethod(LuaItemStack, clear),
365         luamethod(LuaItemStack, replace),
366         luamethod(LuaItemStack, to_string),
367         luamethod(LuaItemStack, to_table),
368         luamethod(LuaItemStack, get_stack_max),
369         luamethod(LuaItemStack, get_free_space),
370         luamethod(LuaItemStack, is_known),
371         luamethod(LuaItemStack, get_definition),
372         luamethod(LuaItemStack, get_tool_capabilities),
373         luamethod(LuaItemStack, add_wear),
374         luamethod(LuaItemStack, add_item),
375         luamethod(LuaItemStack, item_fits),
376         luamethod(LuaItemStack, take_item),
377         luamethod(LuaItemStack, peek_item),
378         {0,0}
379 };
380
381 ModApiItemMod::ModApiItemMod() {
382 }
383
384 /*
385         ItemDefinition
386 */
387
388 // register_item_raw({lots of stuff})
389 int ModApiItemMod::l_register_item_raw(lua_State *L)
390 {
391         NO_MAP_LOCK_REQUIRED;
392         luaL_checktype(L, 1, LUA_TTABLE);
393         int table = 1;
394
395         ScriptApi* scriptIface = get_scriptapi(L);
396
397         // Get the writable item and node definition managers from the server
398         IWritableItemDefManager *idef =
399                         scriptIface->getServer()->getWritableItemDefManager();
400         IWritableNodeDefManager *ndef =
401                         scriptIface->getServer()->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                         STACK_TO_SERVER(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 = STACK_TO_SERVER(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 = STACK_TO_SERVER(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 bool ModApiItemMod::Initialize(lua_State *L,int top) {
492
493         bool retval = true;
494
495         retval &= API_FCT(register_item_raw);
496         retval &= API_FCT(register_alias_raw);
497         retval &= API_FCT(get_content_id);
498         retval &= API_FCT(get_name_from_content_id);
499
500         LuaItemStack::Register(L);
501
502         return retval;
503 }
504
505 ModApiItemMod modapi_item_prototyp;