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