]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_env.cpp
Move core.get_connected_players() implementation to C++
[dragonfireclient.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                 PlayerSAO *sao = player->getPlayerSAO();
652                 if (sao) {
653                         getScriptApiBase(L)->objectrefGetOrCreate(L, sao);
654                         lua_rawseti(L, -2, ++i);
655                 }
656         }
657         return 1;
658 }
659
660 // get_player_by_name(name)
661 int ModApiEnvMod::l_get_player_by_name(lua_State *L)
662 {
663         GET_ENV_PTR;
664
665         // Do it
666         const char *name = luaL_checkstring(L, 1);
667         RemotePlayer *player = env->getPlayer(name);
668         if (player == NULL){
669                 lua_pushnil(L);
670                 return 1;
671         }
672         PlayerSAO *sao = player->getPlayerSAO();
673         if(sao == NULL){
674                 lua_pushnil(L);
675                 return 1;
676         }
677         // Put player on stack
678         getScriptApiBase(L)->objectrefGetOrCreate(L, sao);
679         return 1;
680 }
681
682 // get_objects_inside_radius(pos, radius)
683 int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L)
684 {
685         GET_ENV_PTR;
686
687         // Do it
688         v3f pos = checkFloatPos(L, 1);
689         float radius = readParam<float>(L, 2) * BS;
690         std::vector<u16> ids;
691         env->getObjectsInsideRadius(ids, pos, radius);
692         ScriptApiBase *script = getScriptApiBase(L);
693         lua_createtable(L, ids.size(), 0);
694         std::vector<u16>::const_iterator iter = ids.begin();
695         for(u32 i = 0; iter != ids.end(); ++iter) {
696                 ServerActiveObject *obj = env->getActiveObject(*iter);
697                 if (!obj->isGone()) {
698                         // Insert object reference into table
699                         script->objectrefGetOrCreate(L, obj);
700                         lua_rawseti(L, -2, ++i);
701                 }
702         }
703         return 1;
704 }
705
706 // set_timeofday(val)
707 // val = 0...1
708 int ModApiEnvMod::l_set_timeofday(lua_State *L)
709 {
710         GET_ENV_PTR;
711
712         // Do it
713         float timeofday_f = readParam<float>(L, 1);
714         sanity_check(timeofday_f >= 0.0 && timeofday_f <= 1.0);
715         int timeofday_mh = (int)(timeofday_f * 24000.0);
716         // This should be set directly in the environment but currently
717         // such changes aren't immediately sent to the clients, so call
718         // the server instead.
719         //env->setTimeOfDay(timeofday_mh);
720         getServer(L)->setTimeOfDay(timeofday_mh);
721         return 0;
722 }
723
724 // get_timeofday() -> 0...1
725 int ModApiEnvMod::l_get_timeofday(lua_State *L)
726 {
727         Environment *env = getEnv(L);
728         if (!env) {
729                 return 0;
730         }
731
732         // Do it
733         int timeofday_mh = env->getTimeOfDay();
734         float timeofday_f = (float)timeofday_mh / 24000.0f;
735         lua_pushnumber(L, timeofday_f);
736         return 1;
737 }
738
739 // get_day_count() -> int
740 int ModApiEnvMod::l_get_day_count(lua_State *L)
741 {
742         Environment *env = getEnv(L);
743         if (!env) {
744                 return 0;
745         }
746
747         lua_pushnumber(L, env->getDayCount());
748         return 1;
749 }
750
751 // get_gametime()
752 int ModApiEnvMod::l_get_gametime(lua_State *L)
753 {
754         GET_ENV_PTR;
755
756         int game_time = env->getGameTime();
757         lua_pushnumber(L, game_time);
758         return 1;
759 }
760
761
762 // find_node_near(pos, radius, nodenames, search_center) -> pos or nil
763 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
764 int ModApiEnvMod::l_find_node_near(lua_State *L)
765 {
766         Environment *env = getEnv(L);
767         if (!env) {
768                 return 0;
769         }
770
771         const NodeDefManager *ndef = getGameDef(L)->ndef();
772         v3s16 pos = read_v3s16(L, 1);
773         int radius = luaL_checkinteger(L, 2);
774         std::vector<content_t> filter;
775         if (lua_istable(L, 3)) {
776                 lua_pushnil(L);
777                 while (lua_next(L, 3) != 0) {
778                         // key at index -2 and value at index -1
779                         luaL_checktype(L, -1, LUA_TSTRING);
780                         ndef->getIds(readParam<std::string>(L, -1), filter);
781                         // removes value, keeps key for next iteration
782                         lua_pop(L, 1);
783                 }
784         } else if (lua_isstring(L, 3)) {
785                 ndef->getIds(readParam<std::string>(L, 3), filter);
786         }
787
788         int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1;
789
790 #ifndef SERVER
791         // Client API limitations
792         if (getClient(L))
793                 radius = getClient(L)->CSMClampRadius(pos, radius);
794 #endif
795
796         for (int d = start_radius; d <= radius; d++) {
797                 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
798                 for (const v3s16 &i : list) {
799                         v3s16 p = pos + i;
800                         content_t c = env->getMap().getNode(p).getContent();
801                         if (CONTAINS(filter, c)) {
802                                 push_v3s16(L, p);
803                                 return 1;
804                         }
805                 }
806         }
807         return 0;
808 }
809
810 // find_nodes_in_area(minp, maxp, nodenames) -> list of positions
811 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
812 int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
813 {
814         GET_ENV_PTR;
815
816         v3s16 minp = read_v3s16(L, 1);
817         v3s16 maxp = read_v3s16(L, 2);
818         sortBoxVerticies(minp, maxp);
819
820 #ifndef SERVER
821         const NodeDefManager *ndef = getClient(L) ? getClient(L)->ndef() : getServer(L)->ndef();
822         if (getClient(L)) {
823                 minp = getClient(L)->CSMClampPos(minp);
824                 maxp = getClient(L)->CSMClampPos(maxp);
825         }
826 #else
827         const NodeDefManager *ndef = getServer(L)->ndef();
828 #endif
829
830         v3s16 cube = maxp - minp + 1;
831         // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
832         if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
833                 luaL_error(L, "find_nodes_in_area(): area volume"
834                                 " exceeds allowed value of 4096000");
835                 return 0;
836         }
837
838         std::vector<content_t> filter;
839         if (lua_istable(L, 3)) {
840                 lua_pushnil(L);
841                 while (lua_next(L, 3) != 0) {
842                         // key at index -2 and value at index -1
843                         luaL_checktype(L, -1, LUA_TSTRING);
844                         ndef->getIds(readParam<std::string>(L, -1), filter);
845                         // removes value, keeps key for next iteration
846                         lua_pop(L, 1);
847                 }
848         } else if (lua_isstring(L, 3)) {
849                 ndef->getIds(readParam<std::string>(L, 3), filter);
850         }
851
852         std::vector<u32> individual_count;
853         individual_count.resize(filter.size());
854
855         lua_newtable(L);
856         u64 i = 0;
857         for (s16 x = minp.X; x <= maxp.X; x++)
858         for (s16 y = minp.Y; y <= maxp.Y; y++)
859         for (s16 z = minp.Z; z <= maxp.Z; z++) {
860                 v3s16 p(x, y, z);
861                 content_t c = env->getMap().getNode(p).getContent();
862
863                 std::vector<content_t>::iterator it = std::find(filter.begin(), filter.end(), c);
864                 if (it != filter.end()) {
865                         push_v3s16(L, p);
866                         lua_rawseti(L, -2, ++i);
867
868                         u32 filt_index = it - filter.begin();
869                         individual_count[filt_index]++;
870                 }
871         }
872         lua_newtable(L);
873         for (u32 i = 0; i < filter.size(); i++) {
874                 lua_pushnumber(L, individual_count[i]);
875                 lua_setfield(L, -2, ndef->get(filter[i]).name.c_str());
876         }
877         return 2;
878 }
879
880 // find_nodes_in_area_under_air(minp, maxp, nodenames) -> list of positions
881 // nodenames: e.g. {"ignore", "group:tree"} or "default:dirt"
882 int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
883 {
884         /* Note: A similar but generalized (and therefore slower) version of this
885          * function could be created -- e.g. find_nodes_in_area_under -- which
886          * would accept a node name (or ID?) or list of names that the "above node"
887          * should be.
888          * TODO
889          */
890
891         GET_ENV_PTR;
892
893         v3s16 minp = read_v3s16(L, 1);
894         v3s16 maxp = read_v3s16(L, 2);
895         sortBoxVerticies(minp, maxp);
896
897 #ifndef SERVER
898         const NodeDefManager *ndef = getClient(L) ? getClient(L)->ndef() : getServer(L)->ndef();
899         if (getClient(L)) {
900                 minp = getClient(L)->CSMClampPos(minp);
901                 maxp = getClient(L)->CSMClampPos(maxp);
902         }
903 #else
904         const NodeDefManager *ndef = getServer(L)->ndef();
905 #endif
906
907         v3s16 cube = maxp - minp + 1;
908         // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
909         if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
910                 luaL_error(L, "find_nodes_in_area_under_air(): area volume"
911                                 " exceeds allowed value of 4096000");
912                 return 0;
913         }
914
915         std::vector<content_t> filter;
916
917         if (lua_istable(L, 3)) {
918                 lua_pushnil(L);
919                 while (lua_next(L, 3) != 0) {
920                         // key at index -2 and value at index -1
921                         luaL_checktype(L, -1, LUA_TSTRING);
922                         ndef->getIds(readParam<std::string>(L, -1), filter);
923                         // removes value, keeps key for next iteration
924                         lua_pop(L, 1);
925                 }
926         } else if (lua_isstring(L, 3)) {
927                 ndef->getIds(readParam<std::string>(L, 3), filter);
928         }
929
930         lua_newtable(L);
931         u64 i = 0;
932         for (s16 x = minp.X; x <= maxp.X; x++)
933         for (s16 z = minp.Z; z <= maxp.Z; z++) {
934                 s16 y = minp.Y;
935                 v3s16 p(x, y, z);
936                 content_t c = env->getMap().getNode(p).getContent();
937                 for (; y <= maxp.Y; y++) {
938                         v3s16 psurf(x, y + 1, z);
939                         content_t csurf = env->getMap().getNode(psurf).getContent();
940                         if (c != CONTENT_AIR && csurf == CONTENT_AIR &&
941                                         CONTAINS(filter, c)) {
942                                 push_v3s16(L, v3s16(x, y, z));
943                                 lua_rawseti(L, -2, ++i);
944                         }
945                         c = csurf;
946                 }
947         }
948         return 1;
949 }
950
951 // get_perlin(seeddiff, octaves, persistence, scale)
952 // returns world-specific PerlinNoise
953 int ModApiEnvMod::l_get_perlin(lua_State *L)
954 {
955         GET_ENV_PTR_NO_MAP_LOCK;
956
957         NoiseParams params;
958
959         if (lua_istable(L, 1)) {
960                 read_noiseparams(L, 1, &params);
961         } else {
962                 params.seed    = luaL_checkint(L, 1);
963                 params.octaves = luaL_checkint(L, 2);
964                 params.persist = readParam<float>(L, 3);
965                 params.spread  = v3f(1, 1, 1) * readParam<float>(L, 4);
966         }
967
968         params.seed += (int)env->getServerMap().getSeed();
969
970         LuaPerlinNoise *n = new LuaPerlinNoise(&params);
971         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
972         luaL_getmetatable(L, "PerlinNoise");
973         lua_setmetatable(L, -2);
974         return 1;
975 }
976
977 // get_perlin_map(noiseparams, size)
978 // returns world-specific PerlinNoiseMap
979 int ModApiEnvMod::l_get_perlin_map(lua_State *L)
980 {
981         GET_ENV_PTR_NO_MAP_LOCK;
982
983         NoiseParams np;
984         if (!read_noiseparams(L, 1, &np))
985                 return 0;
986         v3s16 size = read_v3s16(L, 2);
987
988         s32 seed = (s32)(env->getServerMap().getSeed());
989         LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(&np, seed, size);
990         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
991         luaL_getmetatable(L, "PerlinNoiseMap");
992         lua_setmetatable(L, -2);
993         return 1;
994 }
995
996 // get_voxel_manip()
997 // returns voxel manipulator
998 int ModApiEnvMod::l_get_voxel_manip(lua_State *L)
999 {
1000         GET_ENV_PTR;
1001
1002         Map *map = &(env->getMap());
1003         LuaVoxelManip *o = (lua_istable(L, 1) && lua_istable(L, 2)) ?
1004                 new LuaVoxelManip(map, read_v3s16(L, 1), read_v3s16(L, 2)) :
1005                 new LuaVoxelManip(map);
1006
1007         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1008         luaL_getmetatable(L, "VoxelManip");
1009         lua_setmetatable(L, -2);
1010         return 1;
1011 }
1012
1013 // clear_objects([options])
1014 // clear all objects in the environment
1015 // where options = {mode = "full" or "quick"}
1016 int ModApiEnvMod::l_clear_objects(lua_State *L)
1017 {
1018         GET_ENV_PTR;
1019
1020         ClearObjectsMode mode = CLEAR_OBJECTS_MODE_QUICK;
1021         if (lua_istable(L, 1)) {
1022                 mode = (ClearObjectsMode)getenumfield(L, 1, "mode",
1023                         ModApiEnvMod::es_ClearObjectsMode, mode);
1024         }
1025
1026         env->clearObjects(mode);
1027         return 0;
1028 }
1029
1030 // line_of_sight(pos1, pos2) -> true/false, pos
1031 int ModApiEnvMod::l_line_of_sight(lua_State *L)
1032 {
1033         GET_ENV_PTR;
1034
1035         // read position 1 from lua
1036         v3f pos1 = checkFloatPos(L, 1);
1037         // read position 2 from lua
1038         v3f pos2 = checkFloatPos(L, 2);
1039
1040         v3s16 p;
1041
1042         bool success = env->line_of_sight(pos1, pos2, &p);
1043         lua_pushboolean(L, success);
1044         if (!success) {
1045                 push_v3s16(L, p);
1046                 return 2;
1047         }
1048         return 1;
1049 }
1050
1051 // fix_light(p1, p2)
1052 int ModApiEnvMod::l_fix_light(lua_State *L)
1053 {
1054         GET_ENV_PTR;
1055
1056         v3s16 blockpos1 = getContainerPos(read_v3s16(L, 1), MAP_BLOCKSIZE);
1057         v3s16 blockpos2 = getContainerPos(read_v3s16(L, 2), MAP_BLOCKSIZE);
1058         ServerMap &map = env->getServerMap();
1059         std::map<v3s16, MapBlock *> modified_blocks;
1060         bool success = true;
1061         v3s16 blockpos;
1062         for (blockpos.X = blockpos1.X; blockpos.X <= blockpos2.X; blockpos.X++)
1063         for (blockpos.Y = blockpos1.Y; blockpos.Y <= blockpos2.Y; blockpos.Y++)
1064         for (blockpos.Z = blockpos1.Z; blockpos.Z <= blockpos2.Z; blockpos.Z++) {
1065                 success = success & map.repairBlockLight(blockpos, &modified_blocks);
1066         }
1067         if (!modified_blocks.empty()) {
1068                 MapEditEvent event;
1069                 event.type = MEET_OTHER;
1070                 for (auto &modified_block : modified_blocks)
1071                         event.modified_blocks.insert(modified_block.first);
1072
1073                 map.dispatchEvent(event);
1074         }
1075         lua_pushboolean(L, success);
1076
1077         return 1;
1078 }
1079
1080 int ModApiEnvMod::l_raycast(lua_State *L)
1081 {
1082         return LuaRaycast::create_object(L);
1083 }
1084
1085 // load_area(p1, [p2])
1086 // load mapblocks in area p1..p2, but do not generate map
1087 int ModApiEnvMod::l_load_area(lua_State *L)
1088 {
1089         GET_ENV_PTR;
1090         MAP_LOCK_REQUIRED;
1091
1092         Map *map = &(env->getMap());
1093         v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 1));
1094         if (!lua_istable(L, 2)) {
1095                 map->emergeBlock(bp1);
1096         } else {
1097                 v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 2));
1098                 sortBoxVerticies(bp1, bp2);
1099                 for (s16 z = bp1.Z; z <= bp2.Z; z++)
1100                 for (s16 y = bp1.Y; y <= bp2.Y; y++)
1101                 for (s16 x = bp1.X; x <= bp2.X; x++) {
1102                         map->emergeBlock(v3s16(x, y, z));
1103                 }
1104         }
1105
1106         return 0;
1107 }
1108
1109 // emerge_area(p1, p2, [callback, context])
1110 // emerge mapblocks in area p1..p2, calls callback with context upon completion
1111 int ModApiEnvMod::l_emerge_area(lua_State *L)
1112 {
1113         GET_ENV_PTR;
1114
1115         EmergeCompletionCallback callback = NULL;
1116         ScriptCallbackState *state = NULL;
1117
1118         EmergeManager *emerge = getServer(L)->getEmergeManager();
1119
1120         v3s16 bpmin = getNodeBlockPos(read_v3s16(L, 1));
1121         v3s16 bpmax = getNodeBlockPos(read_v3s16(L, 2));
1122         sortBoxVerticies(bpmin, bpmax);
1123
1124         size_t num_blocks = VoxelArea(bpmin, bpmax).getVolume();
1125         assert(num_blocks != 0);
1126
1127         if (lua_isfunction(L, 3)) {
1128                 callback = LuaEmergeAreaCallback;
1129
1130                 lua_pushvalue(L, 3);
1131                 int callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1132
1133                 lua_pushvalue(L, 4);
1134                 int args_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1135
1136                 state = new ScriptCallbackState;
1137                 state->script       = getServer(L)->getScriptIface();
1138                 state->callback_ref = callback_ref;
1139                 state->args_ref     = args_ref;
1140                 state->refcount     = num_blocks;
1141                 state->origin       = getScriptApiBase(L)->getOrigin();
1142         }
1143
1144         for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
1145         for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
1146         for (s16 x = bpmin.X; x <= bpmax.X; x++) {
1147                 emerge->enqueueBlockEmergeEx(v3s16(x, y, z), PEER_ID_INEXISTENT,
1148                         BLOCK_EMERGE_ALLOW_GEN | BLOCK_EMERGE_FORCE_QUEUE, callback, state);
1149         }
1150
1151         return 0;
1152 }
1153
1154 // delete_area(p1, p2)
1155 // delete mapblocks in area p1..p2
1156 int ModApiEnvMod::l_delete_area(lua_State *L)
1157 {
1158         GET_ENV_PTR;
1159
1160         v3s16 bpmin = getNodeBlockPos(read_v3s16(L, 1));
1161         v3s16 bpmax = getNodeBlockPos(read_v3s16(L, 2));
1162         sortBoxVerticies(bpmin, bpmax);
1163
1164         ServerMap &map = env->getServerMap();
1165
1166         MapEditEvent event;
1167         event.type = MEET_OTHER;
1168
1169         bool success = true;
1170         for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
1171         for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
1172         for (s16 x = bpmin.X; x <= bpmax.X; x++) {
1173                 v3s16 bp(x, y, z);
1174                 if (map.deleteBlock(bp)) {
1175                         env->setStaticForActiveObjectsInBlock(bp, false);
1176                         event.modified_blocks.insert(bp);
1177                 } else {
1178                         success = false;
1179                 }
1180         }
1181
1182         map.dispatchEvent(event);
1183         lua_pushboolean(L, success);
1184         return 1;
1185 }
1186
1187 // find_path(pos1, pos2, searchdistance,
1188 //     max_jump, max_drop, algorithm) -> table containing path
1189 int ModApiEnvMod::l_find_path(lua_State *L)
1190 {
1191         GET_ENV_PTR;
1192
1193         v3s16 pos1                  = read_v3s16(L, 1);
1194         v3s16 pos2                  = read_v3s16(L, 2);
1195         unsigned int searchdistance = luaL_checkint(L, 3);
1196         unsigned int max_jump       = luaL_checkint(L, 4);
1197         unsigned int max_drop       = luaL_checkint(L, 5);
1198         PathAlgorithm algo          = PA_PLAIN_NP;
1199         if (!lua_isnil(L, 6)) {
1200                 std::string algorithm = luaL_checkstring(L,6);
1201
1202                 if (algorithm == "A*")
1203                         algo = PA_PLAIN;
1204
1205                 if (algorithm == "Dijkstra")
1206                         algo = PA_DIJKSTRA;
1207         }
1208
1209         std::vector<v3s16> path = get_path(env, pos1, pos2,
1210                 searchdistance, max_jump, max_drop, algo);
1211
1212         if (!path.empty()) {
1213                 lua_newtable(L);
1214                 int top = lua_gettop(L);
1215                 unsigned int index = 1;
1216                 for (const v3s16 &i : path) {
1217                         lua_pushnumber(L,index);
1218                         push_v3s16(L, i);
1219                         lua_settable(L, top);
1220                         index++;
1221                 }
1222                 return 1;
1223         }
1224
1225         return 0;
1226 }
1227
1228 // spawn_tree(pos, treedef)
1229 int ModApiEnvMod::l_spawn_tree(lua_State *L)
1230 {
1231         GET_ENV_PTR;
1232
1233         v3s16 p0 = read_v3s16(L, 1);
1234
1235         treegen::TreeDef tree_def;
1236         std::string trunk,leaves,fruit;
1237         const NodeDefManager *ndef = env->getGameDef()->ndef();
1238
1239         if(lua_istable(L, 2))
1240         {
1241                 getstringfield(L, 2, "axiom", tree_def.initial_axiom);
1242                 getstringfield(L, 2, "rules_a", tree_def.rules_a);
1243                 getstringfield(L, 2, "rules_b", tree_def.rules_b);
1244                 getstringfield(L, 2, "rules_c", tree_def.rules_c);
1245                 getstringfield(L, 2, "rules_d", tree_def.rules_d);
1246                 getstringfield(L, 2, "trunk", trunk);
1247                 tree_def.trunknode=ndef->getId(trunk);
1248                 getstringfield(L, 2, "leaves", leaves);
1249                 tree_def.leavesnode=ndef->getId(leaves);
1250                 tree_def.leaves2_chance=0;
1251                 getstringfield(L, 2, "leaves2", leaves);
1252                 if (!leaves.empty()) {
1253                         tree_def.leaves2node=ndef->getId(leaves);
1254                         getintfield(L, 2, "leaves2_chance", tree_def.leaves2_chance);
1255                 }
1256                 getintfield(L, 2, "angle", tree_def.angle);
1257                 getintfield(L, 2, "iterations", tree_def.iterations);
1258                 if (!getintfield(L, 2, "random_level", tree_def.iterations_random_level))
1259                         tree_def.iterations_random_level = 0;
1260                 getstringfield(L, 2, "trunk_type", tree_def.trunk_type);
1261                 getboolfield(L, 2, "thin_branches", tree_def.thin_branches);
1262                 tree_def.fruit_chance=0;
1263                 getstringfield(L, 2, "fruit", fruit);
1264                 if (!fruit.empty()) {
1265                         tree_def.fruitnode=ndef->getId(fruit);
1266                         getintfield(L, 2, "fruit_chance",tree_def.fruit_chance);
1267                 }
1268                 tree_def.explicit_seed = getintfield(L, 2, "seed", tree_def.seed);
1269         }
1270         else
1271                 return 0;
1272
1273         treegen::error e;
1274         if ((e = treegen::spawn_ltree (env, p0, ndef, tree_def)) != treegen::SUCCESS) {
1275                 if (e == treegen::UNBALANCED_BRACKETS) {
1276                         luaL_error(L, "spawn_tree(): closing ']' has no matching opening bracket");
1277                 } else {
1278                         luaL_error(L, "spawn_tree(): unknown error");
1279                 }
1280         }
1281
1282         return 1;
1283 }
1284
1285 // transforming_liquid_add(pos)
1286 int ModApiEnvMod::l_transforming_liquid_add(lua_State *L)
1287 {
1288         GET_ENV_PTR;
1289
1290         v3s16 p0 = read_v3s16(L, 1);
1291         env->getMap().transforming_liquid_add(p0);
1292         return 1;
1293 }
1294
1295 // forceload_block(blockpos)
1296 // blockpos = {x=num, y=num, z=num}
1297 int ModApiEnvMod::l_forceload_block(lua_State *L)
1298 {
1299         GET_ENV_PTR;
1300
1301         v3s16 blockpos = read_v3s16(L, 1);
1302         env->getForceloadedBlocks()->insert(blockpos);
1303         return 0;
1304 }
1305
1306 // forceload_free_block(blockpos)
1307 // blockpos = {x=num, y=num, z=num}
1308 int ModApiEnvMod::l_forceload_free_block(lua_State *L)
1309 {
1310         GET_ENV_PTR;
1311
1312         v3s16 blockpos = read_v3s16(L, 1);
1313         env->getForceloadedBlocks()->erase(blockpos);
1314         return 0;
1315 }
1316
1317 void ModApiEnvMod::Initialize(lua_State *L, int top)
1318 {
1319         API_FCT(set_node);
1320         API_FCT(bulk_set_node);
1321         API_FCT(add_node);
1322         API_FCT(swap_node);
1323         API_FCT(add_item);
1324         API_FCT(remove_node);
1325         API_FCT(get_node);
1326         API_FCT(get_node_or_nil);
1327         API_FCT(get_node_light);
1328         API_FCT(place_node);
1329         API_FCT(dig_node);
1330         API_FCT(punch_node);
1331         API_FCT(get_node_max_level);
1332         API_FCT(get_node_level);
1333         API_FCT(set_node_level);
1334         API_FCT(add_node_level);
1335         API_FCT(add_entity);
1336         API_FCT(find_nodes_with_meta);
1337         API_FCT(get_meta);
1338         API_FCT(get_node_timer);
1339         API_FCT(get_connected_players);
1340         API_FCT(get_player_by_name);
1341         API_FCT(get_objects_inside_radius);
1342         API_FCT(set_timeofday);
1343         API_FCT(get_timeofday);
1344         API_FCT(get_gametime);
1345         API_FCT(get_day_count);
1346         API_FCT(find_node_near);
1347         API_FCT(find_nodes_in_area);
1348         API_FCT(find_nodes_in_area_under_air);
1349         API_FCT(fix_light);
1350         API_FCT(load_area);
1351         API_FCT(emerge_area);
1352         API_FCT(delete_area);
1353         API_FCT(get_perlin);
1354         API_FCT(get_perlin_map);
1355         API_FCT(get_voxel_manip);
1356         API_FCT(clear_objects);
1357         API_FCT(spawn_tree);
1358         API_FCT(find_path);
1359         API_FCT(line_of_sight);
1360         API_FCT(raycast);
1361         API_FCT(transforming_liquid_add);
1362         API_FCT(forceload_block);
1363         API_FCT(forceload_free_block);
1364 }
1365
1366 void ModApiEnvMod::InitializeClient(lua_State *L, int top)
1367 {
1368         API_FCT(get_node_light);
1369         API_FCT(get_timeofday);
1370         API_FCT(get_node_max_level);
1371         API_FCT(get_node_level);
1372         API_FCT(find_nodes_with_meta);
1373         API_FCT(find_node_near);
1374         API_FCT(find_nodes_in_area);
1375         API_FCT(find_nodes_in_area_under_air);
1376         API_FCT(line_of_sight);
1377         API_FCT(raycast);
1378 }