]> git.lizzy.rs Git - minetest.git/blob - src/script/lua_api/l_env.cpp
Fix missing find_path and line_of_sight
[minetest.git] / src / script / lua_api / l_env.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 "cpp_api/scriptapi.h"
21 #include "lua_api/l_base.h"
22 #include "lua_api/l_env.h"
23 #include "environment.h"
24 #include "server.h"
25 #include "daynightratio.h"
26 #include "util/pointedthing.h"
27 #include "content_sao.h"
28
29 #include "common/c_converter.h"
30 #include "common/c_content.h"
31 #include "common/c_internal.h"
32 #include "lua_api/l_nodemeta.h"
33 #include "lua_api/l_nodetimer.h"
34 #include "lua_api/l_noise.h"
35 #include "treegen.h"
36 #include "pathfinder.h"
37
38
39 #define GET_ENV_PTR ServerEnvironment* env =                                   \
40                                 dynamic_cast<ServerEnvironment*>(getEnv(L));                   \
41                                 if( env == NULL) return 0
42
43 void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
44                 u32 active_object_count, u32 active_object_count_wider)
45 {
46         ScriptApi* scriptIface = SERVER_TO_SA(env);
47         scriptIface->realityCheck();
48
49         lua_State* L = scriptIface->getStack();
50         assert(lua_checkstack(L, 20));
51         StackUnroller stack_unroller(L);
52
53         // Get minetest.registered_abms
54         lua_getglobal(L, "minetest");
55         lua_getfield(L, -1, "registered_abms");
56         luaL_checktype(L, -1, LUA_TTABLE);
57         int registered_abms = lua_gettop(L);
58
59         // Get minetest.registered_abms[m_id]
60         lua_pushnumber(L, m_id);
61         lua_gettable(L, registered_abms);
62         if(lua_isnil(L, -1))
63                 assert(0);
64
65         // Call action
66         luaL_checktype(L, -1, LUA_TTABLE);
67         lua_getfield(L, -1, "action");
68         luaL_checktype(L, -1, LUA_TFUNCTION);
69         push_v3s16(L, p);
70         pushnode(L, n, env->getGameDef()->ndef());
71         lua_pushnumber(L, active_object_count);
72         lua_pushnumber(L, active_object_count_wider);
73         if(lua_pcall(L, 4, 0, 0))
74                 script_error(L, "error: %s", lua_tostring(L, -1));
75 }
76
77 // Exported functions
78
79 // minetest.set_node(pos, node)
80 // pos = {x=num, y=num, z=num}
81 int ModApiEnvMod::l_set_node(lua_State *L)
82 {
83         GET_ENV_PTR;
84
85         INodeDefManager *ndef = env->getGameDef()->ndef();
86         // parameters
87         v3s16 pos = read_v3s16(L, 1);
88         MapNode n = readnode(L, 2, ndef);
89         // Do it
90         bool succeeded = env->setNode(pos, n);
91         lua_pushboolean(L, succeeded);
92         return 1;
93 }
94
95 int ModApiEnvMod::l_add_node(lua_State *L)
96 {
97         return l_set_node(L);
98 }
99
100 // minetest.remove_node(pos)
101 // pos = {x=num, y=num, z=num}
102 int ModApiEnvMod::l_remove_node(lua_State *L)
103 {
104         GET_ENV_PTR;
105
106         // parameters
107         v3s16 pos = read_v3s16(L, 1);
108         // Do it
109         bool succeeded = env->removeNode(pos);
110         lua_pushboolean(L, succeeded);
111         return 1;
112 }
113
114 // minetest.get_node(pos)
115 // pos = {x=num, y=num, z=num}
116 int ModApiEnvMod::l_get_node(lua_State *L)
117 {
118         GET_ENV_PTR;
119
120         // pos
121         v3s16 pos = read_v3s16(L, 1);
122         // Do it
123         MapNode n = env->getMap().getNodeNoEx(pos);
124         // Return node
125         pushnode(L, n, env->getGameDef()->ndef());
126         return 1;
127 }
128
129 // minetest.get_node_or_nil(pos)
130 // pos = {x=num, y=num, z=num}
131 int ModApiEnvMod::l_get_node_or_nil(lua_State *L)
132 {
133         GET_ENV_PTR;
134
135         // pos
136         v3s16 pos = read_v3s16(L, 1);
137         // Do it
138         try{
139                 MapNode n = env->getMap().getNode(pos);
140                 // Return node
141                 pushnode(L, n, env->getGameDef()->ndef());
142                 return 1;
143         } catch(InvalidPositionException &e)
144         {
145                 lua_pushnil(L);
146                 return 1;
147         }
148 }
149
150 // minetest.get_node_light(pos, timeofday)
151 // pos = {x=num, y=num, z=num}
152 // timeofday: nil = current time, 0 = night, 0.5 = day
153 int ModApiEnvMod::l_get_node_light(lua_State *L)
154 {
155         GET_ENV_PTR;
156
157         // Do it
158         v3s16 pos = read_v3s16(L, 1);
159         u32 time_of_day = env->getTimeOfDay();
160         if(lua_isnumber(L, 2))
161                 time_of_day = 24000.0 * lua_tonumber(L, 2);
162         time_of_day %= 24000;
163         u32 dnr = time_to_daynight_ratio(time_of_day, true);
164         try{
165                 MapNode n = env->getMap().getNode(pos);
166                 INodeDefManager *ndef = env->getGameDef()->ndef();
167                 lua_pushinteger(L, n.getLightBlend(dnr, ndef));
168                 return 1;
169         } catch(InvalidPositionException &e)
170         {
171                 lua_pushnil(L);
172                 return 1;
173         }
174 }
175
176 // minetest.place_node(pos, node)
177 // pos = {x=num, y=num, z=num}
178 int ModApiEnvMod::l_place_node(lua_State *L)
179 {
180         GET_ENV_PTR;
181
182         v3s16 pos = read_v3s16(L, 1);
183         MapNode n = readnode(L, 2, env->getGameDef()->ndef());
184
185         // Don't attempt to load non-loaded area as of now
186         MapNode n_old = env->getMap().getNodeNoEx(pos);
187         if(n_old.getContent() == CONTENT_IGNORE){
188                 lua_pushboolean(L, false);
189                 return 1;
190         }
191         // Create item to place
192         INodeDefManager *ndef = getServer(L)->ndef();
193         IItemDefManager *idef = getServer(L)->idef();
194         ItemStack item(ndef->get(n).name, 1, 0, "", idef);
195         // Make pointed position
196         PointedThing pointed;
197         pointed.type = POINTEDTHING_NODE;
198         pointed.node_abovesurface = pos;
199         pointed.node_undersurface = pos + v3s16(0,-1,0);
200         // Place it with a NULL placer (appears in Lua as a non-functional
201         // ObjectRef)
202         bool success = get_scriptapi(L)->item_OnPlace(item, NULL, pointed);
203         lua_pushboolean(L, success);
204         return 1;
205 }
206
207 // minetest.dig_node(pos)
208 // pos = {x=num, y=num, z=num}
209 int ModApiEnvMod::l_dig_node(lua_State *L)
210 {
211         GET_ENV_PTR;
212
213         v3s16 pos = read_v3s16(L, 1);
214
215         // Don't attempt to load non-loaded area as of now
216         MapNode n = env->getMap().getNodeNoEx(pos);
217         if(n.getContent() == CONTENT_IGNORE){
218                 lua_pushboolean(L, false);
219                 return 1;
220         }
221         // Dig it out with a NULL digger (appears in Lua as a
222         // non-functional ObjectRef)
223         bool success = get_scriptapi(L)->node_on_dig(pos, n, NULL);
224         lua_pushboolean(L, success);
225         return 1;
226 }
227
228 // minetest.punch_node(pos)
229 // pos = {x=num, y=num, z=num}
230 int ModApiEnvMod::l_punch_node(lua_State *L)
231 {
232         GET_ENV_PTR;
233
234         v3s16 pos = read_v3s16(L, 1);
235
236         // Don't attempt to load non-loaded area as of now
237         MapNode n = env->getMap().getNodeNoEx(pos);
238         if(n.getContent() == CONTENT_IGNORE){
239                 lua_pushboolean(L, false);
240                 return 1;
241         }
242         // Punch it with a NULL puncher (appears in Lua as a non-functional
243         // ObjectRef)
244         bool success = get_scriptapi(L)->node_on_punch(pos, n, NULL);
245         lua_pushboolean(L, success);
246         return 1;
247 }
248
249 // minetest.get_meta(pos)
250 int ModApiEnvMod::l_get_meta(lua_State *L)
251 {
252         GET_ENV_PTR;
253
254         // Do it
255         v3s16 p = read_v3s16(L, 1);
256         NodeMetaRef::create(L, p, env);
257         return 1;
258 }
259
260 // minetest.get_node_timer(pos)
261 int ModApiEnvMod::l_get_node_timer(lua_State *L)
262 {
263         GET_ENV_PTR;
264
265         // Do it
266         v3s16 p = read_v3s16(L, 1);
267         NodeTimerRef::create(L, p, env);
268         return 1;
269 }
270
271 // minetest.add_entity(pos, entityname) -> ObjectRef or nil
272 // pos = {x=num, y=num, z=num}
273 int ModApiEnvMod::l_add_entity(lua_State *L)
274 {
275         GET_ENV_PTR;
276
277         // pos
278         v3f pos = checkFloatPos(L, 1);
279         // content
280         const char *name = luaL_checkstring(L, 2);
281         // Do it
282         ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
283         int objectid = env->addActiveObject(obj);
284         // If failed to add, return nothing (reads as nil)
285         if(objectid == 0)
286                 return 0;
287         // Return ObjectRef
288         get_scriptapi(L)->objectrefGetOrCreate(obj);
289         return 1;
290 }
291
292 // minetest.add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil
293 // pos = {x=num, y=num, z=num}
294 int ModApiEnvMod::l_add_item(lua_State *L)
295 {
296         GET_ENV_PTR;
297
298         // pos
299         //v3f pos = checkFloatPos(L, 1);
300         // item
301         ItemStack item = read_item(L, 2,getServer(L));
302         if(item.empty() || !item.isKnown(getServer(L)->idef()))
303                 return 0;
304         // Use minetest.spawn_item to spawn a __builtin:item
305         lua_getglobal(L, "minetest");
306         lua_getfield(L, -1, "spawn_item");
307         if(lua_isnil(L, -1))
308                 return 0;
309         lua_pushvalue(L, 1);
310         lua_pushstring(L, item.getItemString().c_str());
311         if(lua_pcall(L, 2, 1, 0))
312                 script_error(L, "error: %s", lua_tostring(L, -1));
313         return 1;
314         /*lua_pushvalue(L, 1);
315         lua_pushstring(L, "__builtin:item");
316         lua_pushstring(L, item.getItemString().c_str());
317         return l_add_entity(L);*/
318         /*// Do it
319         ServerActiveObject *obj = createItemSAO(env, pos, item.getItemString());
320         int objectid = env->addActiveObject(obj);
321         // If failed to add, return nothing (reads as nil)
322         if(objectid == 0)
323                 return 0;
324         // Return ObjectRef
325         objectrefGetOrCreate(L, obj);
326         return 1;*/
327 }
328
329 // minetest.get_player_by_name(name)
330 int ModApiEnvMod::l_get_player_by_name(lua_State *L)
331 {
332         GET_ENV_PTR;
333
334         // Do it
335         const char *name = luaL_checkstring(L, 1);
336         Player *player = env->getPlayer(name);
337         if(player == NULL){
338                 lua_pushnil(L);
339                 return 1;
340         }
341         PlayerSAO *sao = player->getPlayerSAO();
342         if(sao == NULL){
343                 lua_pushnil(L);
344                 return 1;
345         }
346         // Put player on stack
347         get_scriptapi(L)->objectrefGetOrCreate(sao);
348         return 1;
349 }
350
351 // minetest.get_objects_inside_radius(pos, radius)
352 int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L)
353 {
354         // Get the table insert function
355         lua_getglobal(L, "table");
356         lua_getfield(L, -1, "insert");
357         int table_insert = lua_gettop(L);
358
359         GET_ENV_PTR;
360
361         // Do it
362         v3f pos = checkFloatPos(L, 1);
363         float radius = luaL_checknumber(L, 2) * BS;
364         std::set<u16> ids = env->getObjectsInsideRadius(pos, radius);
365         lua_newtable(L);
366         int table = lua_gettop(L);
367         for(std::set<u16>::const_iterator
368                         i = ids.begin(); i != ids.end(); i++){
369                 ServerActiveObject *obj = env->getActiveObject(*i);
370                 // Insert object reference into table
371                 lua_pushvalue(L, table_insert);
372                 lua_pushvalue(L, table);
373                 get_scriptapi(L)->objectrefGetOrCreate(obj);
374                 if(lua_pcall(L, 2, 0, 0))
375                         script_error(L, "error: %s", lua_tostring(L, -1));
376         }
377         return 1;
378 }
379
380 // minetest.set_timeofday(val)
381 // val = 0...1
382 int ModApiEnvMod::l_set_timeofday(lua_State *L)
383 {
384         GET_ENV_PTR;
385
386         // Do it
387         float timeofday_f = luaL_checknumber(L, 1);
388         assert(timeofday_f >= 0.0 && timeofday_f <= 1.0);
389         int timeofday_mh = (int)(timeofday_f * 24000.0);
390         // This should be set directly in the environment but currently
391         // such changes aren't immediately sent to the clients, so call
392         // the server instead.
393         //env->setTimeOfDay(timeofday_mh);
394         getServer(L)->setTimeOfDay(timeofday_mh);
395         return 0;
396 }
397
398 // minetest.get_timeofday() -> 0...1
399 int ModApiEnvMod::l_get_timeofday(lua_State *L)
400 {
401         GET_ENV_PTR;
402
403         // Do it
404         int timeofday_mh = env->getTimeOfDay();
405         float timeofday_f = (float)timeofday_mh / 24000.0;
406         lua_pushnumber(L, timeofday_f);
407         return 1;
408 }
409
410
411 // minetest.find_node_near(pos, radius, nodenames) -> pos or nil
412 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
413 int ModApiEnvMod::l_find_node_near(lua_State *L)
414 {
415         GET_ENV_PTR;
416
417         INodeDefManager *ndef = getServer(L)->ndef();
418         v3s16 pos = read_v3s16(L, 1);
419         int radius = luaL_checkinteger(L, 2);
420         std::set<content_t> filter;
421         if(lua_istable(L, 3)){
422                 int table = 3;
423                 lua_pushnil(L);
424                 while(lua_next(L, table) != 0){
425                         // key at index -2 and value at index -1
426                         luaL_checktype(L, -1, LUA_TSTRING);
427                         ndef->getIds(lua_tostring(L, -1), filter);
428                         // removes value, keeps key for next iteration
429                         lua_pop(L, 1);
430                 }
431         } else if(lua_isstring(L, 3)){
432                 ndef->getIds(lua_tostring(L, 3), filter);
433         }
434
435         for(int d=1; d<=radius; d++){
436                 std::list<v3s16> list;
437                 getFacePositions(list, d);
438                 for(std::list<v3s16>::iterator i = list.begin();
439                                 i != list.end(); ++i){
440                         v3s16 p = pos + (*i);
441                         content_t c = env->getMap().getNodeNoEx(p).getContent();
442                         if(filter.count(c) != 0){
443                                 push_v3s16(L, p);
444                                 return 1;
445                         }
446                 }
447         }
448         return 0;
449 }
450
451 // minetest.find_nodes_in_area(minp, maxp, nodenames) -> list of positions
452 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
453 int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
454 {
455         GET_ENV_PTR;
456
457         INodeDefManager *ndef = getServer(L)->ndef();
458         v3s16 minp = read_v3s16(L, 1);
459         v3s16 maxp = read_v3s16(L, 2);
460         std::set<content_t> filter;
461         if(lua_istable(L, 3)){
462                 int table = 3;
463                 lua_pushnil(L);
464                 while(lua_next(L, table) != 0){
465                         // key at index -2 and value at index -1
466                         luaL_checktype(L, -1, LUA_TSTRING);
467                         ndef->getIds(lua_tostring(L, -1), filter);
468                         // removes value, keeps key for next iteration
469                         lua_pop(L, 1);
470                 }
471         } else if(lua_isstring(L, 3)){
472                 ndef->getIds(lua_tostring(L, 3), filter);
473         }
474
475         // Get the table insert function
476         lua_getglobal(L, "table");
477         lua_getfield(L, -1, "insert");
478         int table_insert = lua_gettop(L);
479
480         lua_newtable(L);
481         int table = lua_gettop(L);
482         for(s16 x=minp.X; x<=maxp.X; x++)
483         for(s16 y=minp.Y; y<=maxp.Y; y++)
484         for(s16 z=minp.Z; z<=maxp.Z; z++)
485         {
486                 v3s16 p(x,y,z);
487                 content_t c = env->getMap().getNodeNoEx(p).getContent();
488                 if(filter.count(c) != 0){
489                         lua_pushvalue(L, table_insert);
490                         lua_pushvalue(L, table);
491                         push_v3s16(L, p);
492                         if(lua_pcall(L, 2, 0, 0))
493                                 script_error(L, "error: %s", lua_tostring(L, -1));
494                 }
495         }
496         return 1;
497 }
498
499 // minetest.get_perlin(seeddiff, octaves, persistence, scale)
500 // returns world-specific PerlinNoise
501 int ModApiEnvMod::l_get_perlin(lua_State *L)
502 {
503         GET_ENV_PTR;
504
505         int seeddiff = luaL_checkint(L, 1);
506         int octaves = luaL_checkint(L, 2);
507         float persistence = luaL_checknumber(L, 3);
508         float scale = luaL_checknumber(L, 4);
509
510         LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale);
511         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
512         luaL_getmetatable(L, "PerlinNoise");
513         lua_setmetatable(L, -2);
514         return 1;
515 }
516
517 // minetest.get_perlin_map(noiseparams, size)
518 // returns world-specific PerlinNoiseMap
519 int ModApiEnvMod::l_get_perlin_map(lua_State *L)
520 {
521         GET_ENV_PTR;
522
523         NoiseParams *np = read_noiseparams(L, 1);
524         if (!np)
525                 return 0;
526         v3s16 size = read_v3s16(L, 2);
527
528         int seed = (int)(env->getServerMap().getSeed());
529         LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(np, seed, size);
530         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
531         luaL_getmetatable(L, "PerlinNoiseMap");
532         lua_setmetatable(L, -2);
533         return 1;
534 }
535
536 // minetest.clear_objects()
537 // clear all objects in the environment
538 int ModApiEnvMod::l_clear_objects(lua_State *L)
539 {
540         GET_ENV_PTR;
541
542         env->clearAllObjects();
543         return 0;
544 }
545
546 // minetest.line_of_sight(pos1, pos2, stepsize) -> true/false
547 int ModApiEnvMod::l_line_of_sight(lua_State *L) {
548         float stepsize = 1.0;
549
550         GET_ENV_PTR;
551
552         // read position 1 from lua
553         v3f pos1 = checkFloatPos(L, 1);
554         // read position 2 from lua
555         v3f pos2 = checkFloatPos(L, 2);
556         //read step size from lua
557         if(lua_isnumber(L, 3))
558         stepsize = lua_tonumber(L, 3);
559
560         return (env->line_of_sight(pos1,pos2,stepsize));
561 }
562
563 // minetest.find_path(pos1, pos2, searchdistance,
564 //     max_jump, max_drop, algorithm) -> table containing path
565 int ModApiEnvMod::l_find_path(lua_State *L)
566 {
567         GET_ENV_PTR;
568
569         v3s16 pos1                  = read_v3s16(L, 1);
570         v3s16 pos2                  = read_v3s16(L, 2);
571         unsigned int searchdistance = luaL_checkint(L, 3);
572         unsigned int max_jump       = luaL_checkint(L, 4);
573         unsigned int max_drop       = luaL_checkint(L, 5);
574         algorithm algo              = A_PLAIN_NP;
575         if(! lua_isnil(L, 6)) {
576                 std::string algorithm       = luaL_checkstring(L,6);
577
578                 if (algorithm == "A*")
579                         algo = A_PLAIN;
580
581                 if (algorithm == "Dijkstra")
582                         algo = DIJKSTRA;
583         }
584
585         std::vector<v3s16> path =
586                         get_Path(env,pos1,pos2,searchdistance,max_jump,max_drop,algo);
587
588         if (path.size() > 0)
589         {
590                 lua_newtable(L);
591                 int top = lua_gettop(L);
592                 unsigned int index = 1;
593                 for (std::vector<v3s16>::iterator i = path.begin(); i != path.end();i++)
594                 {
595                         lua_pushnumber(L,index);
596                         push_v3s16(L, *i);
597                         lua_settable(L, top);
598                         index++;
599                 }
600                 return 1;
601         }
602
603         return 0;
604 }
605
606 // minetest.spawn_tree(pos, treedef)
607 int ModApiEnvMod::l_spawn_tree(lua_State *L)
608 {
609         GET_ENV_PTR;
610
611         v3s16 p0 = read_v3s16(L, 1);
612
613         treegen::TreeDef tree_def;
614         std::string trunk,leaves,fruit;
615         INodeDefManager *ndef = env->getGameDef()->ndef();
616
617         if(lua_istable(L, 2))
618         {
619                 getstringfield(L, 2, "axiom", tree_def.initial_axiom);
620                 getstringfield(L, 2, "rules_a", tree_def.rules_a);
621                 getstringfield(L, 2, "rules_b", tree_def.rules_b);
622                 getstringfield(L, 2, "rules_c", tree_def.rules_c);
623                 getstringfield(L, 2, "rules_d", tree_def.rules_d);
624                 getstringfield(L, 2, "trunk", trunk);
625                 tree_def.trunknode=ndef->getId(trunk);
626                 getstringfield(L, 2, "leaves", leaves);
627                 tree_def.leavesnode=ndef->getId(leaves);
628                 tree_def.leaves2_chance=0;
629                 getstringfield(L, 2, "leaves2", leaves);
630                 if (leaves !="")
631                 {
632                         tree_def.leaves2node=ndef->getId(leaves);
633                         getintfield(L, 2, "leaves2_chance", tree_def.leaves2_chance);
634                 }
635                 getintfield(L, 2, "angle", tree_def.angle);
636                 getintfield(L, 2, "iterations", tree_def.iterations);
637                 getintfield(L, 2, "random_level", tree_def.iterations_random_level);
638                 getstringfield(L, 2, "trunk_type", tree_def.trunk_type);
639                 getboolfield(L, 2, "thin_branches", tree_def.thin_branches);
640                 tree_def.fruit_chance=0;
641                 getstringfield(L, 2, "fruit", fruit);
642                 if (fruit != "")
643                 {
644                         tree_def.fruitnode=ndef->getId(fruit);
645                         getintfield(L, 2, "fruit_chance",tree_def.fruit_chance);
646                 }
647                 getintfield(L, 2, "seed", tree_def.seed);
648         }
649         else
650                 return 0;
651         treegen::spawn_ltree (env, p0, ndef, tree_def);
652         return 1;
653 }
654
655 bool ModApiEnvMod::Initialize(lua_State *L,int top)
656 {
657
658         bool retval = true;
659
660         retval &= API_FCT(set_node);
661         retval &= API_FCT(add_node);
662         retval &= API_FCT(add_item);
663         retval &= API_FCT(remove_node);
664         retval &= API_FCT(get_node);
665         retval &= API_FCT(get_node_or_nil);
666         retval &= API_FCT(get_node_light);
667         retval &= API_FCT(place_node);
668         retval &= API_FCT(dig_node);
669         retval &= API_FCT(punch_node);
670         retval &= API_FCT(add_entity);
671         retval &= API_FCT(get_meta);
672         retval &= API_FCT(get_node_timer);
673         retval &= API_FCT(get_player_by_name);
674         retval &= API_FCT(get_objects_inside_radius);
675         retval &= API_FCT(set_timeofday);
676         retval &= API_FCT(get_timeofday);
677         retval &= API_FCT(find_node_near);
678         retval &= API_FCT(find_nodes_in_area);
679         retval &= API_FCT(get_perlin);
680         retval &= API_FCT(get_perlin_map);
681         retval &= API_FCT(clear_objects);
682         retval &= API_FCT(spawn_tree);
683         retval &= API_FCT(find_path);
684         retval &= API_FCT(line_of_sight);
685
686         return retval;
687 }
688
689 ModApiEnvMod modapienv_prototype;