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