Fix potential problem with core.get_connected_players()
[oweals/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 "lua_api/l_env.h"
21 #include "lua_api/l_internal.h"
22 #include "lua_api/l_nodemeta.h"
23 #include "lua_api/l_nodetimer.h"
24 #include "lua_api/l_noise.h"
25 #include "lua_api/l_vmanip.h"
26 #include "common/c_converter.h"
27 #include "common/c_content.h"
28 #include <algorithm>
29 #include "scripting_server.h"
30 #include "environment.h"
31 #include "mapblock.h"
32 #include "server.h"
33 #include "nodedef.h"
34 #include "daynightratio.h"
35 #include "util/pointedthing.h"
36 #include "content_sao.h"
37 #include "mapgen/treegen.h"
38 #include "emerge.h"
39 #include "pathfinder.h"
40 #include "face_position_cache.h"
41 #include "remoteplayer.h"
42 #ifndef SERVER
43 #include "client/client.h"
44 #endif
45
46 struct EnumString ModApiEnvMod::es_ClearObjectsMode[] =
47 {
48         {CLEAR_OBJECTS_MODE_FULL,  "full"},
49         {CLEAR_OBJECTS_MODE_QUICK, "quick"},
50         {0, NULL},
51 };
52
53 ///////////////////////////////////////////////////////////////////////////////
54
55
56 void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
57                 u32 active_object_count, u32 active_object_count_wider)
58 {
59         ServerScripting *scriptIface = env->getScriptIface();
60         scriptIface->realityCheck();
61
62         lua_State *L = scriptIface->getStack();
63         sanity_check(lua_checkstack(L, 20));
64         StackUnroller stack_unroller(L);
65
66         int error_handler = PUSH_ERROR_HANDLER(L);
67
68         // Get registered_abms
69         lua_getglobal(L, "core");
70         lua_getfield(L, -1, "registered_abms");
71         luaL_checktype(L, -1, LUA_TTABLE);
72         lua_remove(L, -2); // Remove core
73
74         // Get registered_abms[m_id]
75         lua_pushnumber(L, m_id);
76         lua_gettable(L, -2);
77         if(lua_isnil(L, -1))
78                 FATAL_ERROR("");
79         lua_remove(L, -2); // Remove registered_abms
80
81         scriptIface->setOriginFromTable(-1);
82
83         // Call action
84         luaL_checktype(L, -1, LUA_TTABLE);
85         lua_getfield(L, -1, "action");
86         luaL_checktype(L, -1, LUA_TFUNCTION);
87         lua_remove(L, -2); // Remove registered_abms[m_id]
88         push_v3s16(L, p);
89         pushnode(L, n, env->getGameDef()->ndef());
90         lua_pushnumber(L, active_object_count);
91         lua_pushnumber(L, active_object_count_wider);
92
93         int result = lua_pcall(L, 4, 0, error_handler);
94         if (result)
95                 scriptIface->scriptError(result, "LuaABM::trigger");
96
97         lua_pop(L, 1); // Pop error handler
98 }
99
100 void LuaLBM::trigger(ServerEnvironment *env, v3s16 p, MapNode n)
101 {
102         ServerScripting *scriptIface = env->getScriptIface();
103         scriptIface->realityCheck();
104
105         lua_State *L = scriptIface->getStack();
106         sanity_check(lua_checkstack(L, 20));
107         StackUnroller stack_unroller(L);
108
109         int error_handler = PUSH_ERROR_HANDLER(L);
110
111         // Get registered_lbms
112         lua_getglobal(L, "core");
113         lua_getfield(L, -1, "registered_lbms");
114         luaL_checktype(L, -1, LUA_TTABLE);
115         lua_remove(L, -2); // Remove core
116
117         // Get registered_lbms[m_id]
118         lua_pushnumber(L, m_id);
119         lua_gettable(L, -2);
120         FATAL_ERROR_IF(lua_isnil(L, -1), "Entry with given id not found in registered_lbms table");
121         lua_remove(L, -2); // Remove registered_lbms
122
123         scriptIface->setOriginFromTable(-1);
124
125         // Call action
126         luaL_checktype(L, -1, LUA_TTABLE);
127         lua_getfield(L, -1, "action");
128         luaL_checktype(L, -1, LUA_TFUNCTION);
129         lua_remove(L, -2); // Remove registered_lbms[m_id]
130         push_v3s16(L, p);
131         pushnode(L, n, env->getGameDef()->ndef());
132
133         int result = lua_pcall(L, 2, 0, error_handler);
134         if (result)
135                 scriptIface->scriptError(result, "LuaLBM::trigger");
136
137         lua_pop(L, 1); // Pop error handler
138 }
139
140 int LuaRaycast::l_next(lua_State *L)
141 {
142         MAP_LOCK_REQUIRED;
143         GET_ENV_PTR;
144
145         bool csm = false;
146 #ifndef SERVER
147         csm = getClient(L) != nullptr;
148 #endif
149
150         LuaRaycast *o = checkobject(L, 1);
151         PointedThing pointed;
152         env->continueRaycast(&o->state, &pointed);
153         if (pointed.type == POINTEDTHING_NOTHING)
154                 lua_pushnil(L);
155         else
156                 push_pointed_thing(L, pointed, csm, true);
157
158         return 1;
159 }
160
161 int LuaRaycast::create_object(lua_State *L)
162 {
163         NO_MAP_LOCK_REQUIRED;
164
165         bool objects = true;
166         bool liquids = false;
167
168         v3f pos1 = checkFloatPos(L, 1);
169         v3f pos2 = checkFloatPos(L, 2);
170         if (lua_isboolean(L, 3)) {
171                 objects = readParam<bool>(L, 3);
172         }
173         if (lua_isboolean(L, 4)) {
174                 liquids = readParam<bool>(L, 4);
175         }
176
177         LuaRaycast *o = new LuaRaycast(core::line3d<f32>(pos1, pos2),
178                 objects, liquids);
179
180         *(void **) (lua_newuserdata(L, sizeof(void *))) = o;
181         luaL_getmetatable(L, className);
182         lua_setmetatable(L, -2);
183         return 1;
184 }
185
186 LuaRaycast *LuaRaycast::checkobject(lua_State *L, int narg)
187 {
188         NO_MAP_LOCK_REQUIRED;
189
190         luaL_checktype(L, narg, LUA_TUSERDATA);
191         void *ud = luaL_checkudata(L, narg, className);
192         if (!ud)
193                 luaL_typerror(L, narg, className);
194         return *(LuaRaycast **) ud;
195 }
196
197 int LuaRaycast::gc_object(lua_State *L)
198 {
199         LuaRaycast *o = *(LuaRaycast **) (lua_touserdata(L, 1));
200         delete o;
201         return 0;
202 }
203
204 void LuaRaycast::Register(lua_State *L)
205 {
206         lua_newtable(L);
207         int methodtable = lua_gettop(L);
208         luaL_newmetatable(L, className);
209         int metatable = lua_gettop(L);
210
211         lua_pushliteral(L, "__metatable");
212         lua_pushvalue(L, methodtable);
213         lua_settable(L, metatable);
214
215         lua_pushliteral(L, "__index");
216         lua_pushvalue(L, methodtable);
217         lua_settable(L, metatable);
218
219         lua_pushliteral(L, "__gc");
220         lua_pushcfunction(L, gc_object);
221         lua_settable(L, metatable);
222
223         lua_pushliteral(L, "__call");
224         lua_pushcfunction(L, l_next);
225         lua_settable(L, metatable);
226
227         lua_pop(L, 1);
228
229         luaL_openlib(L, 0, methods, 0);
230         lua_pop(L, 1);
231
232         lua_register(L, className, create_object);
233 }
234
235 const char LuaRaycast::className[] = "Raycast";
236 const luaL_Reg LuaRaycast::methods[] =
237 {
238         luamethod(LuaRaycast, next),
239         { 0, 0 }
240 };
241
242 void LuaEmergeAreaCallback(v3s16 blockpos, EmergeAction action, void *param)
243 {
244         ScriptCallbackState *state = (ScriptCallbackState *)param;
245         assert(state != NULL);
246         assert(state->script != NULL);
247         assert(state->refcount > 0);
248
249         // state must be protected by envlock
250         Server *server = state->script->getServer();
251         MutexAutoLock envlock(server->m_env_mutex);
252
253         state->refcount--;
254
255         state->script->on_emerge_area_completion(blockpos, action, state);
256
257         if (state->refcount == 0)
258                 delete state;
259 }
260
261 // Exported functions
262
263 // set_node(pos, node)
264 // pos = {x=num, y=num, z=num}
265 int ModApiEnvMod::l_set_node(lua_State *L)
266 {
267         GET_ENV_PTR;
268
269         const NodeDefManager *ndef = env->getGameDef()->ndef();
270         // parameters
271         v3s16 pos = read_v3s16(L, 1);
272         MapNode n = readnode(L, 2, ndef);
273         // Do it
274         bool succeeded = env->setNode(pos, n);
275         lua_pushboolean(L, succeeded);
276         return 1;
277 }
278
279 // bulk_set_node([pos1, pos2, ...], node)
280 // pos = {x=num, y=num, z=num}
281 int ModApiEnvMod::l_bulk_set_node(lua_State *L)
282 {
283         GET_ENV_PTR;
284
285         const NodeDefManager *ndef = env->getGameDef()->ndef();
286         // parameters
287         if (!lua_istable(L, 1)) {
288                 return 0;
289         }
290
291         s32 len = lua_objlen(L, 1);
292         if (len == 0) {
293                 lua_pushboolean(L, true);
294                 return 1;
295         }
296
297         MapNode n = readnode(L, 2, ndef);
298
299         // Do it
300         bool succeeded = true;
301         for (s32 i = 1; i <= len; i++) {
302                 lua_rawgeti(L, 1, i);
303                 if (!env->setNode(read_v3s16(L, -1), n))
304                         succeeded = false;
305                 lua_pop(L, 1);
306         }
307
308         lua_pushboolean(L, succeeded);
309         return 1;
310 }
311
312 int ModApiEnvMod::l_add_node(lua_State *L)
313 {
314         return l_set_node(L);
315 }
316
317 // remove_node(pos)
318 // pos = {x=num, y=num, z=num}
319 int ModApiEnvMod::l_remove_node(lua_State *L)
320 {
321         GET_ENV_PTR;
322
323         // parameters
324         v3s16 pos = read_v3s16(L, 1);
325         // Do it
326         bool succeeded = env->removeNode(pos);
327         lua_pushboolean(L, succeeded);
328         return 1;
329 }
330
331 // swap_node(pos, node)
332 // pos = {x=num, y=num, z=num}
333 int ModApiEnvMod::l_swap_node(lua_State *L)
334 {
335         GET_ENV_PTR;
336
337         const NodeDefManager *ndef = env->getGameDef()->ndef();
338         // parameters
339         v3s16 pos = read_v3s16(L, 1);
340         MapNode n = readnode(L, 2, ndef);
341         // Do it
342         bool succeeded = env->swapNode(pos, n);
343         lua_pushboolean(L, succeeded);
344         return 1;
345 }
346
347 // get_node(pos)
348 // pos = {x=num, y=num, z=num}
349 int ModApiEnvMod::l_get_node(lua_State *L)
350 {
351         GET_ENV_PTR;
352
353         // pos
354         v3s16 pos = read_v3s16(L, 1);
355         // Do it
356         MapNode n = env->getMap().getNode(pos);
357         // Return node
358         pushnode(L, n, env->getGameDef()->ndef());
359         return 1;
360 }
361
362 // get_node_or_nil(pos)
363 // pos = {x=num, y=num, z=num}
364 int ModApiEnvMod::l_get_node_or_nil(lua_State *L)
365 {
366         GET_ENV_PTR;
367
368         // pos
369         v3s16 pos = read_v3s16(L, 1);
370         // Do it
371         bool pos_ok;
372         MapNode n = env->getMap().getNode(pos, &pos_ok);
373         if (pos_ok) {
374                 // Return node
375                 pushnode(L, n, env->getGameDef()->ndef());
376         } else {
377                 lua_pushnil(L);
378         }
379         return 1;
380 }
381
382 // get_node_light(pos, timeofday)
383 // pos = {x=num, y=num, z=num}
384 // timeofday: nil = current time, 0 = night, 0.5 = day
385 int ModApiEnvMod::l_get_node_light(lua_State *L)
386 {
387         GET_ENV_PTR;
388
389         // Do it
390         v3s16 pos = read_v3s16(L, 1);
391         u32 time_of_day = env->getTimeOfDay();
392         if(lua_isnumber(L, 2))
393                 time_of_day = 24000.0 * lua_tonumber(L, 2);
394         time_of_day %= 24000;
395         u32 dnr = time_to_daynight_ratio(time_of_day, true);
396
397         bool is_position_ok;
398         MapNode n = env->getMap().getNode(pos, &is_position_ok);
399         if (is_position_ok) {
400                 const NodeDefManager *ndef = env->getGameDef()->ndef();
401                 lua_pushinteger(L, n.getLightBlend(dnr, ndef));
402         } else {
403                 lua_pushnil(L);
404         }
405         return 1;
406 }
407
408 // place_node(pos, node)
409 // pos = {x=num, y=num, z=num}
410 int ModApiEnvMod::l_place_node(lua_State *L)
411 {
412         GET_ENV_PTR;
413
414         ScriptApiItem *scriptIfaceItem = getScriptApi<ScriptApiItem>(L);
415         Server *server = getServer(L);
416         const NodeDefManager *ndef = server->ndef();
417         IItemDefManager *idef = server->idef();
418
419         v3s16 pos = read_v3s16(L, 1);
420         MapNode n = readnode(L, 2, ndef);
421
422         // Don't attempt to load non-loaded area as of now
423         MapNode n_old = env->getMap().getNode(pos);
424         if(n_old.getContent() == CONTENT_IGNORE){
425                 lua_pushboolean(L, false);
426                 return 1;
427         }
428         // Create item to place
429         ItemStack item(ndef->get(n).name, 1, 0, idef);
430         // Make pointed position
431         PointedThing pointed;
432         pointed.type = POINTEDTHING_NODE;
433         pointed.node_abovesurface = pos;
434         pointed.node_undersurface = pos + v3s16(0,-1,0);
435         // Place it with a NULL placer (appears in Lua as nil)
436         bool success = scriptIfaceItem->item_OnPlace(item, nullptr, pointed);
437         lua_pushboolean(L, success);
438         return 1;
439 }
440
441 // dig_node(pos)
442 // pos = {x=num, y=num, z=num}
443 int ModApiEnvMod::l_dig_node(lua_State *L)
444 {
445         GET_ENV_PTR;
446
447         ScriptApiNode *scriptIfaceNode = getScriptApi<ScriptApiNode>(L);
448
449         v3s16 pos = read_v3s16(L, 1);
450
451         // Don't attempt to load non-loaded area as of now
452         MapNode n = env->getMap().getNode(pos);
453         if(n.getContent() == CONTENT_IGNORE){
454                 lua_pushboolean(L, false);
455                 return 1;
456         }
457         // Dig it out with a NULL digger (appears in Lua as a
458         // non-functional ObjectRef)
459         bool success = scriptIfaceNode->node_on_dig(pos, n, NULL);
460         lua_pushboolean(L, success);
461         return 1;
462 }
463
464 // punch_node(pos)
465 // pos = {x=num, y=num, z=num}
466 int ModApiEnvMod::l_punch_node(lua_State *L)
467 {
468         GET_ENV_PTR;
469
470         ScriptApiNode *scriptIfaceNode = getScriptApi<ScriptApiNode>(L);
471
472         v3s16 pos = read_v3s16(L, 1);
473
474         // Don't attempt to load non-loaded area as of now
475         MapNode n = env->getMap().getNode(pos);
476         if(n.getContent() == CONTENT_IGNORE){
477                 lua_pushboolean(L, false);
478                 return 1;
479         }
480         // Punch it with a NULL puncher (appears in Lua as a non-functional
481         // ObjectRef)
482         bool success = scriptIfaceNode->node_on_punch(pos, n, NULL, PointedThing());
483         lua_pushboolean(L, success);
484         return 1;
485 }
486
487 // get_node_max_level(pos)
488 // pos = {x=num, y=num, z=num}
489 int ModApiEnvMod::l_get_node_max_level(lua_State *L)
490 {
491         Environment *env = getEnv(L);
492         if (!env) {
493                 return 0;
494         }
495
496         v3s16 pos = read_v3s16(L, 1);
497         MapNode n = env->getMap().getNode(pos);
498         lua_pushnumber(L, n.getMaxLevel(env->getGameDef()->ndef()));
499         return 1;
500 }
501
502 // get_node_level(pos)
503 // pos = {x=num, y=num, z=num}
504 int ModApiEnvMod::l_get_node_level(lua_State *L)
505 {
506         Environment *env = getEnv(L);
507         if (!env) {
508                 return 0;
509         }
510
511         v3s16 pos = read_v3s16(L, 1);
512         MapNode n = env->getMap().getNode(pos);
513         lua_pushnumber(L, n.getLevel(env->getGameDef()->ndef()));
514         return 1;
515 }
516
517 // set_node_level(pos, level)
518 // pos = {x=num, y=num, z=num}
519 // level: 0..63
520 int ModApiEnvMod::l_set_node_level(lua_State *L)
521 {
522         GET_ENV_PTR;
523
524         v3s16 pos = read_v3s16(L, 1);
525         u8 level = 1;
526         if(lua_isnumber(L, 2))
527                 level = lua_tonumber(L, 2);
528         MapNode n = env->getMap().getNode(pos);
529         lua_pushnumber(L, n.setLevel(env->getGameDef()->ndef(), level));
530         env->setNode(pos, n);
531         return 1;
532 }
533
534 // add_node_level(pos, level)
535 // pos = {x=num, y=num, z=num}
536 // level: 0..63
537 int ModApiEnvMod::l_add_node_level(lua_State *L)
538 {
539         GET_ENV_PTR;
540
541         v3s16 pos = read_v3s16(L, 1);
542         u8 level = 1;
543         if(lua_isnumber(L, 2))
544                 level = lua_tonumber(L, 2);
545         MapNode n = env->getMap().getNode(pos);
546         lua_pushnumber(L, n.addLevel(env->getGameDef()->ndef(), level));
547         env->setNode(pos, n);
548         return 1;
549 }
550
551 // find_nodes_with_meta(pos1, pos2)
552 int ModApiEnvMod::l_find_nodes_with_meta(lua_State *L)
553 {
554         GET_ENV_PTR;
555
556         std::vector<v3s16> positions = env->getMap().findNodesWithMetadata(
557                 check_v3s16(L, 1), check_v3s16(L, 2));
558
559         lua_newtable(L);
560         for (size_t i = 0; i != positions.size(); i++) {
561                 push_v3s16(L, positions[i]);
562                 lua_rawseti(L, -2, i + 1);
563         }
564
565         return 1;
566 }
567
568 // get_meta(pos)
569 int ModApiEnvMod::l_get_meta(lua_State *L)
570 {
571         GET_ENV_PTR;
572
573         // Do it
574         v3s16 p = read_v3s16(L, 1);
575         NodeMetaRef::create(L, p, env);
576         return 1;
577 }
578
579 // get_node_timer(pos)
580 int ModApiEnvMod::l_get_node_timer(lua_State *L)
581 {
582         GET_ENV_PTR;
583
584         // Do it
585         v3s16 p = read_v3s16(L, 1);
586         NodeTimerRef::create(L, p, env);
587         return 1;
588 }
589
590 // add_entity(pos, entityname, [staticdata]) -> ObjectRef or nil
591 // pos = {x=num, y=num, z=num}
592 int ModApiEnvMod::l_add_entity(lua_State *L)
593 {
594         GET_ENV_PTR;
595
596         // pos
597         v3f pos = checkFloatPos(L, 1);
598         // content
599         const char *name = luaL_checkstring(L, 2);
600         // staticdata
601         const char *staticdata = luaL_optstring(L, 3, "");
602         // Do it
603         ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, staticdata);
604         int objectid = env->addActiveObject(obj);
605         // If failed to add, return nothing (reads as nil)
606         if(objectid == 0)
607                 return 0;
608         // Return ObjectRef
609         getScriptApiBase(L)->objectrefGetOrCreate(L, obj);
610         return 1;
611 }
612
613 // add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil
614 // pos = {x=num, y=num, z=num}
615 int ModApiEnvMod::l_add_item(lua_State *L)
616 {
617         GET_ENV_PTR;
618
619         // pos
620         //v3f pos = checkFloatPos(L, 1);
621         // item
622         ItemStack item = read_item(L, 2,getServer(L)->idef());
623         if(item.empty() || !item.isKnown(getServer(L)->idef()))
624                 return 0;
625
626         int error_handler = PUSH_ERROR_HANDLER(L);
627
628         // Use spawn_item to spawn a __builtin:item
629         lua_getglobal(L, "core");
630         lua_getfield(L, -1, "spawn_item");
631         lua_remove(L, -2); // Remove core
632         if(lua_isnil(L, -1))
633                 return 0;
634         lua_pushvalue(L, 1);
635         lua_pushstring(L, item.getItemString().c_str());
636
637         PCALL_RESL(L, lua_pcall(L, 2, 1, error_handler));
638
639         lua_remove(L, error_handler);
640         return 1;
641 }
642
643 // get_connected_players()
644 int ModApiEnvMod::l_get_connected_players(lua_State *L)
645 {
646         GET_ENV_PTR;
647
648         lua_createtable(L, env->getPlayerCount(), 0);
649         u32 i = 0;
650         for (RemotePlayer *player : env->getPlayers()) {
651                 if (player->getPeerId() == PEER_ID_INEXISTENT)
652                         continue;
653                 PlayerSAO *sao = player->getPlayerSAO();
654                 if (sao) {
655                         getScriptApiBase(L)->objectrefGetOrCreate(L, sao);
656                         lua_rawseti(L, -2, ++i);
657                 }
658         }
659         return 1;
660 }
661
662 // get_player_by_name(name)
663 int ModApiEnvMod::l_get_player_by_name(lua_State *L)
664 {
665         GET_ENV_PTR;
666
667         // Do it
668         const char *name = luaL_checkstring(L, 1);
669         RemotePlayer *player = env->getPlayer(name);
670         if (player == NULL){
671                 lua_pushnil(L);
672                 return 1;
673         }
674         PlayerSAO *sao = player->getPlayerSAO();
675         if(sao == NULL){
676                 lua_pushnil(L);
677                 return 1;
678         }
679         // Put player on stack
680         getScriptApiBase(L)->objectrefGetOrCreate(L, sao);
681         return 1;
682 }
683
684 // get_objects_inside_radius(pos, radius)
685 int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L)
686 {
687         GET_ENV_PTR;
688
689         // Do it
690         v3f pos = checkFloatPos(L, 1);
691         float radius = readParam<float>(L, 2) * BS;
692         std::vector<u16> ids;
693         env->getObjectsInsideRadius(ids, pos, radius);
694         ScriptApiBase *script = getScriptApiBase(L);
695         lua_createtable(L, ids.size(), 0);
696         std::vector<u16>::const_iterator iter = ids.begin();
697         for(u32 i = 0; iter != ids.end(); ++iter) {
698                 ServerActiveObject *obj = env->getActiveObject(*iter);
699                 if (!obj->isGone()) {
700                         // Insert object reference into table
701                         script->objectrefGetOrCreate(L, obj);
702                         lua_rawseti(L, -2, ++i);
703                 }
704         }
705         return 1;
706 }
707
708 // set_timeofday(val)
709 // val = 0...1
710 int ModApiEnvMod::l_set_timeofday(lua_State *L)
711 {
712         GET_ENV_PTR;
713
714         // Do it
715         float timeofday_f = readParam<float>(L, 1);
716         sanity_check(timeofday_f >= 0.0 && timeofday_f <= 1.0);
717         int timeofday_mh = (int)(timeofday_f * 24000.0);
718         // This should be set directly in the environment but currently
719         // such changes aren't immediately sent to the clients, so call
720         // the server instead.
721         //env->setTimeOfDay(timeofday_mh);
722         getServer(L)->setTimeOfDay(timeofday_mh);
723         return 0;
724 }
725
726 // get_timeofday() -> 0...1
727 int ModApiEnvMod::l_get_timeofday(lua_State *L)
728 {
729         Environment *env = getEnv(L);
730         if (!env) {
731                 return 0;
732         }
733
734         // Do it
735         int timeofday_mh = env->getTimeOfDay();
736         float timeofday_f = (float)timeofday_mh / 24000.0f;
737         lua_pushnumber(L, timeofday_f);
738         return 1;
739 }
740
741 // get_day_count() -> int
742 int ModApiEnvMod::l_get_day_count(lua_State *L)
743 {
744         Environment *env = getEnv(L);
745         if (!env) {
746                 return 0;
747         }
748
749         lua_pushnumber(L, env->getDayCount());
750         return 1;
751 }
752
753 // get_gametime()
754 int ModApiEnvMod::l_get_gametime(lua_State *L)
755 {
756         GET_ENV_PTR;
757
758         int game_time = env->getGameTime();
759         lua_pushnumber(L, game_time);
760         return 1;
761 }
762
763
764 // find_node_near(pos, radius, nodenames, search_center) -> pos or nil
765 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
766 int ModApiEnvMod::l_find_node_near(lua_State *L)
767 {
768         Environment *env = getEnv(L);
769         if (!env) {
770                 return 0;
771         }
772
773         const NodeDefManager *ndef = getGameDef(L)->ndef();
774         v3s16 pos = read_v3s16(L, 1);
775         int radius = luaL_checkinteger(L, 2);
776         std::vector<content_t> filter;
777         if (lua_istable(L, 3)) {
778                 lua_pushnil(L);
779                 while (lua_next(L, 3) != 0) {
780                         // key at index -2 and value at index -1
781                         luaL_checktype(L, -1, LUA_TSTRING);
782                         ndef->getIds(readParam<std::string>(L, -1), filter);
783                         // removes value, keeps key for next iteration
784                         lua_pop(L, 1);
785                 }
786         } else if (lua_isstring(L, 3)) {
787                 ndef->getIds(readParam<std::string>(L, 3), filter);
788         }
789
790         int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1;
791
792 #ifndef SERVER
793         // Client API limitations
794         if (getClient(L))
795                 radius = getClient(L)->CSMClampRadius(pos, radius);
796 #endif
797
798         for (int d = start_radius; d <= radius; d++) {
799                 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
800                 for (const v3s16 &i : list) {
801                         v3s16 p = pos + i;
802                         content_t c = env->getMap().getNode(p).getContent();
803                         if (CONTAINS(filter, c)) {
804                                 push_v3s16(L, p);
805                                 return 1;
806                         }
807                 }
808         }
809         return 0;
810 }
811
812 // find_nodes_in_area(minp, maxp, nodenames) -> list of positions
813 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
814 int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
815 {
816         GET_ENV_PTR;
817
818         v3s16 minp = read_v3s16(L, 1);
819         v3s16 maxp = read_v3s16(L, 2);
820         sortBoxVerticies(minp, maxp);
821
822 #ifndef SERVER
823         const NodeDefManager *ndef = getClient(L) ? getClient(L)->ndef() : getServer(L)->ndef();
824         if (getClient(L)) {
825                 minp = getClient(L)->CSMClampPos(minp);
826                 maxp = getClient(L)->CSMClampPos(maxp);
827         }
828 #else
829         const NodeDefManager *ndef = getServer(L)->ndef();
830 #endif
831
832         v3s16 cube = maxp - minp + 1;
833         // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
834         if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
835                 luaL_error(L, "find_nodes_in_area(): area volume"
836                                 " exceeds allowed value of 4096000");
837                 return 0;
838         }
839
840         std::vector<content_t> filter;
841         if (lua_istable(L, 3)) {
842                 lua_pushnil(L);
843                 while (lua_next(L, 3) != 0) {
844                         // key at index -2 and value at index -1
845                         luaL_checktype(L, -1, LUA_TSTRING);
846                         ndef->getIds(readParam<std::string>(L, -1), filter);
847                         // removes value, keeps key for next iteration
848                         lua_pop(L, 1);
849                 }
850         } else if (lua_isstring(L, 3)) {
851                 ndef->getIds(readParam<std::string>(L, 3), filter);
852         }
853
854         std::vector<u32> individual_count;
855         individual_count.resize(filter.size());
856
857         lua_newtable(L);
858         u64 i = 0;
859         for (s16 x = minp.X; x <= maxp.X; x++)
860         for (s16 y = minp.Y; y <= maxp.Y; y++)
861         for (s16 z = minp.Z; z <= maxp.Z; z++) {
862                 v3s16 p(x, y, z);
863                 content_t c = env->getMap().getNode(p).getContent();
864
865                 std::vector<content_t>::iterator it = std::find(filter.begin(), filter.end(), c);
866                 if (it != filter.end()) {
867                         push_v3s16(L, p);
868                         lua_rawseti(L, -2, ++i);
869
870                         u32 filt_index = it - filter.begin();
871                         individual_count[filt_index]++;
872                 }
873         }
874         lua_newtable(L);
875         for (u32 i = 0; i < filter.size(); i++) {
876                 lua_pushnumber(L, individual_count[i]);
877                 lua_setfield(L, -2, ndef->get(filter[i]).name.c_str());
878         }
879         return 2;
880 }
881
882 // find_nodes_in_area_under_air(minp, maxp, nodenames) -> list of positions
883 // nodenames: e.g. {"ignore", "group:tree"} or "default:dirt"
884 int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
885 {
886         /* Note: A similar but generalized (and therefore slower) version of this
887          * function could be created -- e.g. find_nodes_in_area_under -- which
888          * would accept a node name (or ID?) or list of names that the "above node"
889          * should be.
890          * TODO
891          */
892
893         GET_ENV_PTR;
894
895         v3s16 minp = read_v3s16(L, 1);
896         v3s16 maxp = read_v3s16(L, 2);
897         sortBoxVerticies(minp, maxp);
898
899 #ifndef SERVER
900         const NodeDefManager *ndef = getClient(L) ? getClient(L)->ndef() : getServer(L)->ndef();
901         if (getClient(L)) {
902                 minp = getClient(L)->CSMClampPos(minp);
903                 maxp = getClient(L)->CSMClampPos(maxp);
904         }
905 #else
906         const NodeDefManager *ndef = getServer(L)->ndef();
907 #endif
908
909         v3s16 cube = maxp - minp + 1;
910         // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
911         if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
912                 luaL_error(L, "find_nodes_in_area_under_air(): area volume"
913                                 " exceeds allowed value of 4096000");
914                 return 0;
915         }
916
917         std::vector<content_t> filter;
918
919         if (lua_istable(L, 3)) {
920                 lua_pushnil(L);
921                 while (lua_next(L, 3) != 0) {
922                         // key at index -2 and value at index -1
923                         luaL_checktype(L, -1, LUA_TSTRING);
924                         ndef->getIds(readParam<std::string>(L, -1), filter);
925                         // removes value, keeps key for next iteration
926                         lua_pop(L, 1);
927                 }
928         } else if (lua_isstring(L, 3)) {
929                 ndef->getIds(readParam<std::string>(L, 3), filter);
930         }
931
932         lua_newtable(L);
933         u64 i = 0;
934         for (s16 x = minp.X; x <= maxp.X; x++)
935         for (s16 z = minp.Z; z <= maxp.Z; z++) {
936                 s16 y = minp.Y;
937                 v3s16 p(x, y, z);
938                 content_t c = env->getMap().getNode(p).getContent();
939                 for (; y <= maxp.Y; y++) {
940                         v3s16 psurf(x, y + 1, z);
941                         content_t csurf = env->getMap().getNode(psurf).getContent();
942                         if (c != CONTENT_AIR && csurf == CONTENT_AIR &&
943                                         CONTAINS(filter, c)) {
944                                 push_v3s16(L, v3s16(x, y, z));
945                                 lua_rawseti(L, -2, ++i);
946                         }
947                         c = csurf;
948                 }
949         }
950         return 1;
951 }
952
953 // get_perlin(seeddiff, octaves, persistence, scale)
954 // returns world-specific PerlinNoise
955 int ModApiEnvMod::l_get_perlin(lua_State *L)
956 {
957         GET_ENV_PTR_NO_MAP_LOCK;
958
959         NoiseParams params;
960
961         if (lua_istable(L, 1)) {
962                 read_noiseparams(L, 1, &params);
963         } else {
964                 params.seed    = luaL_checkint(L, 1);
965                 params.octaves = luaL_checkint(L, 2);
966                 params.persist = readParam<float>(L, 3);
967                 params.spread  = v3f(1, 1, 1) * readParam<float>(L, 4);
968         }
969
970         params.seed += (int)env->getServerMap().getSeed();
971
972         LuaPerlinNoise *n = new LuaPerlinNoise(&params);
973         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
974         luaL_getmetatable(L, "PerlinNoise");
975         lua_setmetatable(L, -2);
976         return 1;
977 }
978
979 // get_perlin_map(noiseparams, size)
980 // returns world-specific PerlinNoiseMap
981 int ModApiEnvMod::l_get_perlin_map(lua_State *L)
982 {
983         GET_ENV_PTR_NO_MAP_LOCK;
984
985         NoiseParams np;
986         if (!read_noiseparams(L, 1, &np))
987                 return 0;
988         v3s16 size = read_v3s16(L, 2);
989
990         s32 seed = (s32)(env->getServerMap().getSeed());
991         LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(&np, seed, size);
992         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
993         luaL_getmetatable(L, "PerlinNoiseMap");
994         lua_setmetatable(L, -2);
995         return 1;
996 }
997
998 // get_voxel_manip()
999 // returns voxel manipulator
1000 int ModApiEnvMod::l_get_voxel_manip(lua_State *L)
1001 {
1002         GET_ENV_PTR;
1003
1004         Map *map = &(env->getMap());
1005         LuaVoxelManip *o = (lua_istable(L, 1) && lua_istable(L, 2)) ?
1006                 new LuaVoxelManip(map, read_v3s16(L, 1), read_v3s16(L, 2)) :
1007                 new LuaVoxelManip(map);
1008
1009         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1010         luaL_getmetatable(L, "VoxelManip");
1011         lua_setmetatable(L, -2);
1012         return 1;
1013 }
1014
1015 // clear_objects([options])
1016 // clear all objects in the environment
1017 // where options = {mode = "full" or "quick"}
1018 int ModApiEnvMod::l_clear_objects(lua_State *L)
1019 {
1020         GET_ENV_PTR;
1021
1022         ClearObjectsMode mode = CLEAR_OBJECTS_MODE_QUICK;
1023         if (lua_istable(L, 1)) {
1024                 mode = (ClearObjectsMode)getenumfield(L, 1, "mode",
1025                         ModApiEnvMod::es_ClearObjectsMode, mode);
1026         }
1027
1028         env->clearObjects(mode);
1029         return 0;
1030 }
1031
1032 // line_of_sight(pos1, pos2) -> true/false, pos
1033 int ModApiEnvMod::l_line_of_sight(lua_State *L)
1034 {
1035         GET_ENV_PTR;
1036
1037         // read position 1 from lua
1038         v3f pos1 = checkFloatPos(L, 1);
1039         // read position 2 from lua
1040         v3f pos2 = checkFloatPos(L, 2);
1041
1042         v3s16 p;
1043
1044         bool success = env->line_of_sight(pos1, pos2, &p);
1045         lua_pushboolean(L, success);
1046         if (!success) {
1047                 push_v3s16(L, p);
1048                 return 2;
1049         }
1050         return 1;
1051 }
1052
1053 // fix_light(p1, p2)
1054 int ModApiEnvMod::l_fix_light(lua_State *L)
1055 {
1056         GET_ENV_PTR;
1057
1058         v3s16 blockpos1 = getContainerPos(read_v3s16(L, 1), MAP_BLOCKSIZE);
1059         v3s16 blockpos2 = getContainerPos(read_v3s16(L, 2), MAP_BLOCKSIZE);
1060         ServerMap &map = env->getServerMap();
1061         std::map<v3s16, MapBlock *> modified_blocks;
1062         bool success = true;
1063         v3s16 blockpos;
1064         for (blockpos.X = blockpos1.X; blockpos.X <= blockpos2.X; blockpos.X++)
1065         for (blockpos.Y = blockpos1.Y; blockpos.Y <= blockpos2.Y; blockpos.Y++)
1066         for (blockpos.Z = blockpos1.Z; blockpos.Z <= blockpos2.Z; blockpos.Z++) {
1067                 success = success & map.repairBlockLight(blockpos, &modified_blocks);
1068         }
1069         if (!modified_blocks.empty()) {
1070                 MapEditEvent event;
1071                 event.type = MEET_OTHER;
1072                 for (auto &modified_block : modified_blocks)
1073                         event.modified_blocks.insert(modified_block.first);
1074
1075                 map.dispatchEvent(event);
1076         }
1077         lua_pushboolean(L, success);
1078
1079         return 1;
1080 }
1081
1082 int ModApiEnvMod::l_raycast(lua_State *L)
1083 {
1084         return LuaRaycast::create_object(L);
1085 }
1086
1087 // load_area(p1, [p2])
1088 // load mapblocks in area p1..p2, but do not generate map
1089 int ModApiEnvMod::l_load_area(lua_State *L)
1090 {
1091         GET_ENV_PTR;
1092         MAP_LOCK_REQUIRED;
1093
1094         Map *map = &(env->getMap());
1095         v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 1));
1096         if (!lua_istable(L, 2)) {
1097                 map->emergeBlock(bp1);
1098         } else {
1099                 v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 2));
1100                 sortBoxVerticies(bp1, bp2);
1101                 for (s16 z = bp1.Z; z <= bp2.Z; z++)
1102                 for (s16 y = bp1.Y; y <= bp2.Y; y++)
1103                 for (s16 x = bp1.X; x <= bp2.X; x++) {
1104                         map->emergeBlock(v3s16(x, y, z));
1105                 }
1106         }
1107
1108         return 0;
1109 }
1110
1111 // emerge_area(p1, p2, [callback, context])
1112 // emerge mapblocks in area p1..p2, calls callback with context upon completion
1113 int ModApiEnvMod::l_emerge_area(lua_State *L)
1114 {
1115         GET_ENV_PTR;
1116
1117         EmergeCompletionCallback callback = NULL;
1118         ScriptCallbackState *state = NULL;
1119
1120         EmergeManager *emerge = getServer(L)->getEmergeManager();
1121
1122         v3s16 bpmin = getNodeBlockPos(read_v3s16(L, 1));
1123         v3s16 bpmax = getNodeBlockPos(read_v3s16(L, 2));
1124         sortBoxVerticies(bpmin, bpmax);
1125
1126         size_t num_blocks = VoxelArea(bpmin, bpmax).getVolume();
1127         assert(num_blocks != 0);
1128
1129         if (lua_isfunction(L, 3)) {
1130                 callback = LuaEmergeAreaCallback;
1131
1132                 lua_pushvalue(L, 3);
1133                 int callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1134
1135                 lua_pushvalue(L, 4);
1136                 int args_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1137
1138                 state = new ScriptCallbackState;
1139                 state->script       = getServer(L)->getScriptIface();
1140                 state->callback_ref = callback_ref;
1141                 state->args_ref     = args_ref;
1142                 state->refcount     = num_blocks;
1143                 state->origin       = getScriptApiBase(L)->getOrigin();
1144         }
1145
1146         for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
1147         for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
1148         for (s16 x = bpmin.X; x <= bpmax.X; x++) {
1149                 emerge->enqueueBlockEmergeEx(v3s16(x, y, z), PEER_ID_INEXISTENT,
1150                         BLOCK_EMERGE_ALLOW_GEN | BLOCK_EMERGE_FORCE_QUEUE, callback, state);
1151         }
1152
1153         return 0;
1154 }
1155
1156 // delete_area(p1, p2)
1157 // delete mapblocks in area p1..p2
1158 int ModApiEnvMod::l_delete_area(lua_State *L)
1159 {
1160         GET_ENV_PTR;
1161
1162         v3s16 bpmin = getNodeBlockPos(read_v3s16(L, 1));
1163         v3s16 bpmax = getNodeBlockPos(read_v3s16(L, 2));
1164         sortBoxVerticies(bpmin, bpmax);
1165
1166         ServerMap &map = env->getServerMap();
1167
1168         MapEditEvent event;
1169         event.type = MEET_OTHER;
1170
1171         bool success = true;
1172         for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
1173         for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
1174         for (s16 x = bpmin.X; x <= bpmax.X; x++) {
1175                 v3s16 bp(x, y, z);
1176                 if (map.deleteBlock(bp)) {
1177                         env->setStaticForActiveObjectsInBlock(bp, false);
1178                         event.modified_blocks.insert(bp);
1179                 } else {
1180                         success = false;
1181                 }
1182         }
1183
1184         map.dispatchEvent(event);
1185         lua_pushboolean(L, success);
1186         return 1;
1187 }
1188
1189 // find_path(pos1, pos2, searchdistance,
1190 //     max_jump, max_drop, algorithm) -> table containing path
1191 int ModApiEnvMod::l_find_path(lua_State *L)
1192 {
1193         GET_ENV_PTR;
1194
1195         v3s16 pos1                  = read_v3s16(L, 1);
1196         v3s16 pos2                  = read_v3s16(L, 2);
1197         unsigned int searchdistance = luaL_checkint(L, 3);
1198         unsigned int max_jump       = luaL_checkint(L, 4);
1199         unsigned int max_drop       = luaL_checkint(L, 5);
1200         PathAlgorithm algo          = PA_PLAIN_NP;
1201         if (!lua_isnil(L, 6)) {
1202                 std::string algorithm = luaL_checkstring(L,6);
1203
1204                 if (algorithm == "A*")
1205                         algo = PA_PLAIN;
1206
1207                 if (algorithm == "Dijkstra")
1208                         algo = PA_DIJKSTRA;
1209         }
1210
1211         std::vector<v3s16> path = get_path(env, pos1, pos2,
1212                 searchdistance, max_jump, max_drop, algo);
1213
1214         if (!path.empty()) {
1215                 lua_newtable(L);
1216                 int top = lua_gettop(L);
1217                 unsigned int index = 1;
1218                 for (const v3s16 &i : path) {
1219                         lua_pushnumber(L,index);
1220                         push_v3s16(L, i);
1221                         lua_settable(L, top);
1222                         index++;
1223                 }
1224                 return 1;
1225         }
1226
1227         return 0;
1228 }
1229
1230 // spawn_tree(pos, treedef)
1231 int ModApiEnvMod::l_spawn_tree(lua_State *L)
1232 {
1233         GET_ENV_PTR;
1234
1235         v3s16 p0 = read_v3s16(L, 1);
1236
1237         treegen::TreeDef tree_def;
1238         std::string trunk,leaves,fruit;
1239         const NodeDefManager *ndef = env->getGameDef()->ndef();
1240
1241         if(lua_istable(L, 2))
1242         {
1243                 getstringfield(L, 2, "axiom", tree_def.initial_axiom);
1244                 getstringfield(L, 2, "rules_a", tree_def.rules_a);
1245                 getstringfield(L, 2, "rules_b", tree_def.rules_b);
1246                 getstringfield(L, 2, "rules_c", tree_def.rules_c);
1247                 getstringfield(L, 2, "rules_d", tree_def.rules_d);
1248                 getstringfield(L, 2, "trunk", trunk);
1249                 tree_def.trunknode=ndef->getId(trunk);
1250                 getstringfield(L, 2, "leaves", leaves);
1251                 tree_def.leavesnode=ndef->getId(leaves);
1252                 tree_def.leaves2_chance=0;
1253                 getstringfield(L, 2, "leaves2", leaves);
1254                 if (!leaves.empty()) {
1255                         tree_def.leaves2node=ndef->getId(leaves);
1256                         getintfield(L, 2, "leaves2_chance", tree_def.leaves2_chance);
1257                 }
1258                 getintfield(L, 2, "angle", tree_def.angle);
1259                 getintfield(L, 2, "iterations", tree_def.iterations);
1260                 if (!getintfield(L, 2, "random_level", tree_def.iterations_random_level))
1261                         tree_def.iterations_random_level = 0;
1262                 getstringfield(L, 2, "trunk_type", tree_def.trunk_type);
1263                 getboolfield(L, 2, "thin_branches", tree_def.thin_branches);
1264                 tree_def.fruit_chance=0;
1265                 getstringfield(L, 2, "fruit", fruit);
1266                 if (!fruit.empty()) {
1267                         tree_def.fruitnode=ndef->getId(fruit);
1268                         getintfield(L, 2, "fruit_chance",tree_def.fruit_chance);
1269                 }
1270                 tree_def.explicit_seed = getintfield(L, 2, "seed", tree_def.seed);
1271         }
1272         else
1273                 return 0;
1274
1275         treegen::error e;
1276         if ((e = treegen::spawn_ltree (env, p0, ndef, tree_def)) != treegen::SUCCESS) {
1277                 if (e == treegen::UNBALANCED_BRACKETS) {
1278                         luaL_error(L, "spawn_tree(): closing ']' has no matching opening bracket");
1279                 } else {
1280                         luaL_error(L, "spawn_tree(): unknown error");
1281                 }
1282         }
1283
1284         return 1;
1285 }
1286
1287 // transforming_liquid_add(pos)
1288 int ModApiEnvMod::l_transforming_liquid_add(lua_State *L)
1289 {
1290         GET_ENV_PTR;
1291
1292         v3s16 p0 = read_v3s16(L, 1);
1293         env->getMap().transforming_liquid_add(p0);
1294         return 1;
1295 }
1296
1297 // forceload_block(blockpos)
1298 // blockpos = {x=num, y=num, z=num}
1299 int ModApiEnvMod::l_forceload_block(lua_State *L)
1300 {
1301         GET_ENV_PTR;
1302
1303         v3s16 blockpos = read_v3s16(L, 1);
1304         env->getForceloadedBlocks()->insert(blockpos);
1305         return 0;
1306 }
1307
1308 // forceload_free_block(blockpos)
1309 // blockpos = {x=num, y=num, z=num}
1310 int ModApiEnvMod::l_forceload_free_block(lua_State *L)
1311 {
1312         GET_ENV_PTR;
1313
1314         v3s16 blockpos = read_v3s16(L, 1);
1315         env->getForceloadedBlocks()->erase(blockpos);
1316         return 0;
1317 }
1318
1319 void ModApiEnvMod::Initialize(lua_State *L, int top)
1320 {
1321         API_FCT(set_node);
1322         API_FCT(bulk_set_node);
1323         API_FCT(add_node);
1324         API_FCT(swap_node);
1325         API_FCT(add_item);
1326         API_FCT(remove_node);
1327         API_FCT(get_node);
1328         API_FCT(get_node_or_nil);
1329         API_FCT(get_node_light);
1330         API_FCT(place_node);
1331         API_FCT(dig_node);
1332         API_FCT(punch_node);
1333         API_FCT(get_node_max_level);
1334         API_FCT(get_node_level);
1335         API_FCT(set_node_level);
1336         API_FCT(add_node_level);
1337         API_FCT(add_entity);
1338         API_FCT(find_nodes_with_meta);
1339         API_FCT(get_meta);
1340         API_FCT(get_node_timer);
1341         API_FCT(get_connected_players);
1342         API_FCT(get_player_by_name);
1343         API_FCT(get_objects_inside_radius);
1344         API_FCT(set_timeofday);
1345         API_FCT(get_timeofday);
1346         API_FCT(get_gametime);
1347         API_FCT(get_day_count);
1348         API_FCT(find_node_near);
1349         API_FCT(find_nodes_in_area);
1350         API_FCT(find_nodes_in_area_under_air);
1351         API_FCT(fix_light);
1352         API_FCT(load_area);
1353         API_FCT(emerge_area);
1354         API_FCT(delete_area);
1355         API_FCT(get_perlin);
1356         API_FCT(get_perlin_map);
1357         API_FCT(get_voxel_manip);
1358         API_FCT(clear_objects);
1359         API_FCT(spawn_tree);
1360         API_FCT(find_path);
1361         API_FCT(line_of_sight);
1362         API_FCT(raycast);
1363         API_FCT(transforming_liquid_add);
1364         API_FCT(forceload_block);
1365         API_FCT(forceload_free_block);
1366 }
1367
1368 void ModApiEnvMod::InitializeClient(lua_State *L, int top)
1369 {
1370         API_FCT(get_node_light);
1371         API_FCT(get_timeofday);
1372         API_FCT(get_node_max_level);
1373         API_FCT(get_node_level);
1374         API_FCT(find_nodes_with_meta);
1375         API_FCT(find_node_near);
1376         API_FCT(find_nodes_in_area);
1377         API_FCT(find_nodes_in_area_under_air);
1378         API_FCT(line_of_sight);
1379         API_FCT(raycast);
1380 }