Drop content_sao.{cpp,h}
[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 <algorithm>
21 #include "lua_api/l_env.h"
22 #include "lua_api/l_internal.h"
23 #include "lua_api/l_nodemeta.h"
24 #include "lua_api/l_nodetimer.h"
25 #include "lua_api/l_noise.h"
26 #include "lua_api/l_vmanip.h"
27 #include "common/c_converter.h"
28 #include "common/c_content.h"
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 "mapgen/treegen.h"
37 #include "emerge.h"
38 #include "pathfinder.h"
39 #include "face_position_cache.h"
40 #include "remoteplayer.h"
41 #include "server/luaentity_sao.h"
42 #include "server/player_sao.h"
43 #ifndef SERVER
44 #include "client/client.h"
45 #endif
46
47 struct EnumString ModApiEnvMod::es_ClearObjectsMode[] =
48 {
49         {CLEAR_OBJECTS_MODE_FULL,  "full"},
50         {CLEAR_OBJECTS_MODE_QUICK, "quick"},
51         {0, NULL},
52 };
53
54 ///////////////////////////////////////////////////////////////////////////////
55
56
57 void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
58                 u32 active_object_count, u32 active_object_count_wider)
59 {
60         ServerScripting *scriptIface = env->getScriptIface();
61         scriptIface->realityCheck();
62
63         lua_State *L = scriptIface->getStack();
64         sanity_check(lua_checkstack(L, 20));
65         StackUnroller stack_unroller(L);
66
67         int error_handler = PUSH_ERROR_HANDLER(L);
68
69         // Get registered_abms
70         lua_getglobal(L, "core");
71         lua_getfield(L, -1, "registered_abms");
72         luaL_checktype(L, -1, LUA_TTABLE);
73         lua_remove(L, -2); // Remove core
74
75         // Get registered_abms[m_id]
76         lua_pushnumber(L, m_id);
77         lua_gettable(L, -2);
78         if(lua_isnil(L, -1))
79                 FATAL_ERROR("");
80         lua_remove(L, -2); // Remove registered_abms
81
82         scriptIface->setOriginFromTable(-1);
83
84         // Call action
85         luaL_checktype(L, -1, LUA_TTABLE);
86         lua_getfield(L, -1, "action");
87         luaL_checktype(L, -1, LUA_TFUNCTION);
88         lua_remove(L, -2); // Remove registered_abms[m_id]
89         push_v3s16(L, p);
90         pushnode(L, n, env->getGameDef()->ndef());
91         lua_pushnumber(L, active_object_count);
92         lua_pushnumber(L, active_object_count_wider);
93
94         int result = lua_pcall(L, 4, 0, error_handler);
95         if (result)
96                 scriptIface->scriptError(result, "LuaABM::trigger");
97
98         lua_pop(L, 1); // Pop error handler
99 }
100
101 void LuaLBM::trigger(ServerEnvironment *env, v3s16 p, MapNode n)
102 {
103         ServerScripting *scriptIface = env->getScriptIface();
104         scriptIface->realityCheck();
105
106         lua_State *L = scriptIface->getStack();
107         sanity_check(lua_checkstack(L, 20));
108         StackUnroller stack_unroller(L);
109
110         int error_handler = PUSH_ERROR_HANDLER(L);
111
112         // Get registered_lbms
113         lua_getglobal(L, "core");
114         lua_getfield(L, -1, "registered_lbms");
115         luaL_checktype(L, -1, LUA_TTABLE);
116         lua_remove(L, -2); // Remove core
117
118         // Get registered_lbms[m_id]
119         lua_pushnumber(L, m_id);
120         lua_gettable(L, -2);
121         FATAL_ERROR_IF(lua_isnil(L, -1), "Entry with given id not found in registered_lbms table");
122         lua_remove(L, -2); // Remove registered_lbms
123
124         scriptIface->setOriginFromTable(-1);
125
126         // Call action
127         luaL_checktype(L, -1, LUA_TTABLE);
128         lua_getfield(L, -1, "action");
129         luaL_checktype(L, -1, LUA_TFUNCTION);
130         lua_remove(L, -2); // Remove registered_lbms[m_id]
131         push_v3s16(L, p);
132         pushnode(L, n, env->getGameDef()->ndef());
133
134         int result = lua_pcall(L, 2, 0, error_handler);
135         if (result)
136                 scriptIface->scriptError(result, "LuaLBM::trigger");
137
138         lua_pop(L, 1); // Pop error handler
139 }
140
141 int LuaRaycast::l_next(lua_State *L)
142 {
143         GET_PLAIN_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_PLAIN_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         GET_PLAIN_ENV_PTR;
492
493         v3s16 pos = read_v3s16(L, 1);
494         MapNode n = env->getMap().getNode(pos);
495         lua_pushnumber(L, n.getMaxLevel(env->getGameDef()->ndef()));
496         return 1;
497 }
498
499 // get_node_level(pos)
500 // pos = {x=num, y=num, z=num}
501 int ModApiEnvMod::l_get_node_level(lua_State *L)
502 {
503         GET_PLAIN_ENV_PTR;
504
505         v3s16 pos = read_v3s16(L, 1);
506         MapNode n = env->getMap().getNode(pos);
507         lua_pushnumber(L, n.getLevel(env->getGameDef()->ndef()));
508         return 1;
509 }
510
511 // set_node_level(pos, level)
512 // pos = {x=num, y=num, z=num}
513 // level: 0..63
514 int ModApiEnvMod::l_set_node_level(lua_State *L)
515 {
516         GET_ENV_PTR;
517
518         v3s16 pos = read_v3s16(L, 1);
519         u8 level = 1;
520         if(lua_isnumber(L, 2))
521                 level = lua_tonumber(L, 2);
522         MapNode n = env->getMap().getNode(pos);
523         lua_pushnumber(L, n.setLevel(env->getGameDef()->ndef(), level));
524         env->setNode(pos, n);
525         return 1;
526 }
527
528 // add_node_level(pos, level)
529 // pos = {x=num, y=num, z=num}
530 // level: 0..63
531 int ModApiEnvMod::l_add_node_level(lua_State *L)
532 {
533         GET_ENV_PTR;
534
535         v3s16 pos = read_v3s16(L, 1);
536         u8 level = 1;
537         if(lua_isnumber(L, 2))
538                 level = lua_tonumber(L, 2);
539         MapNode n = env->getMap().getNode(pos);
540         lua_pushnumber(L, n.addLevel(env->getGameDef()->ndef(), level));
541         env->setNode(pos, n);
542         return 1;
543 }
544
545 // find_nodes_with_meta(pos1, pos2)
546 int ModApiEnvMod::l_find_nodes_with_meta(lua_State *L)
547 {
548         GET_PLAIN_ENV_PTR;
549
550         std::vector<v3s16> positions = env->getMap().findNodesWithMetadata(
551                 check_v3s16(L, 1), check_v3s16(L, 2));
552
553         lua_newtable(L);
554         for (size_t i = 0; i != positions.size(); i++) {
555                 push_v3s16(L, positions[i]);
556                 lua_rawseti(L, -2, i + 1);
557         }
558
559         return 1;
560 }
561
562 // get_meta(pos)
563 int ModApiEnvMod::l_get_meta(lua_State *L)
564 {
565         GET_ENV_PTR;
566
567         // Do it
568         v3s16 p = read_v3s16(L, 1);
569         NodeMetaRef::create(L, p, env);
570         return 1;
571 }
572
573 // get_node_timer(pos)
574 int ModApiEnvMod::l_get_node_timer(lua_State *L)
575 {
576         GET_ENV_PTR;
577
578         // Do it
579         v3s16 p = read_v3s16(L, 1);
580         NodeTimerRef::create(L, p, env);
581         return 1;
582 }
583
584 // add_entity(pos, entityname, [staticdata]) -> ObjectRef or nil
585 // pos = {x=num, y=num, z=num}
586 int ModApiEnvMod::l_add_entity(lua_State *L)
587 {
588         GET_ENV_PTR;
589
590         // pos
591         v3f pos = checkFloatPos(L, 1);
592         // content
593         const char *name = luaL_checkstring(L, 2);
594         // staticdata
595         const char *staticdata = luaL_optstring(L, 3, "");
596         // Do it
597         ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, staticdata);
598         int objectid = env->addActiveObject(obj);
599         // If failed to add, return nothing (reads as nil)
600         if(objectid == 0)
601                 return 0;
602         // Return ObjectRef
603         getScriptApiBase(L)->objectrefGetOrCreate(L, obj);
604         return 1;
605 }
606
607 // add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil
608 // pos = {x=num, y=num, z=num}
609 int ModApiEnvMod::l_add_item(lua_State *L)
610 {
611         GET_ENV_PTR;
612
613         // pos
614         //v3f pos = checkFloatPos(L, 1);
615         // item
616         ItemStack item = read_item(L, 2,getServer(L)->idef());
617         if(item.empty() || !item.isKnown(getServer(L)->idef()))
618                 return 0;
619
620         int error_handler = PUSH_ERROR_HANDLER(L);
621
622         // Use spawn_item to spawn a __builtin:item
623         lua_getglobal(L, "core");
624         lua_getfield(L, -1, "spawn_item");
625         lua_remove(L, -2); // Remove core
626         if(lua_isnil(L, -1))
627                 return 0;
628         lua_pushvalue(L, 1);
629         lua_pushstring(L, item.getItemString().c_str());
630
631         PCALL_RESL(L, lua_pcall(L, 2, 1, error_handler));
632
633         lua_remove(L, error_handler);
634         return 1;
635 }
636
637 // get_connected_players()
638 int ModApiEnvMod::l_get_connected_players(lua_State *L)
639 {
640         ServerEnvironment *env = (ServerEnvironment *) getEnv(L);
641         if (!env) {
642                 log_deprecated(L, "Calling get_connected_players() at mod load time"
643                                 " is deprecated");
644                 lua_createtable(L, 0, 0);
645                 return 1;
646         }
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 && !sao->isGone()) {
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 || player->getPeerId() == PEER_ID_INEXISTENT)
671                 return 0;
672         PlayerSAO *sao = player->getPlayerSAO();
673         if (!sao || sao->isGone())
674                 return 0;
675         // Put player on stack
676         getScriptApiBase(L)->objectrefGetOrCreate(L, sao);
677         return 1;
678 }
679
680 // get_objects_inside_radius(pos, radius)
681 int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L)
682 {
683         GET_ENV_PTR;
684
685         // Do it
686         v3f pos = checkFloatPos(L, 1);
687         float radius = readParam<float>(L, 2) * BS;
688         std::vector<u16> ids;
689         env->getObjectsInsideRadius(ids, pos, radius);
690         ScriptApiBase *script = getScriptApiBase(L);
691         lua_createtable(L, ids.size(), 0);
692         std::vector<u16>::const_iterator iter = ids.begin();
693         for(u32 i = 0; iter != ids.end(); ++iter) {
694                 ServerActiveObject *obj = env->getActiveObject(*iter);
695                 if (!obj->isGone()) {
696                         // Insert object reference into table
697                         script->objectrefGetOrCreate(L, obj);
698                         lua_rawseti(L, -2, ++i);
699                 }
700         }
701         return 1;
702 }
703
704 // set_timeofday(val)
705 // val = 0...1
706 int ModApiEnvMod::l_set_timeofday(lua_State *L)
707 {
708         GET_ENV_PTR;
709
710         // Do it
711         float timeofday_f = readParam<float>(L, 1);
712         sanity_check(timeofday_f >= 0.0 && timeofday_f <= 1.0);
713         int timeofday_mh = (int)(timeofday_f * 24000.0);
714         // This should be set directly in the environment but currently
715         // such changes aren't immediately sent to the clients, so call
716         // the server instead.
717         //env->setTimeOfDay(timeofday_mh);
718         getServer(L)->setTimeOfDay(timeofday_mh);
719         return 0;
720 }
721
722 // get_timeofday() -> 0...1
723 int ModApiEnvMod::l_get_timeofday(lua_State *L)
724 {
725         GET_PLAIN_ENV_PTR;
726
727         // Do it
728         int timeofday_mh = env->getTimeOfDay();
729         float timeofday_f = (float)timeofday_mh / 24000.0f;
730         lua_pushnumber(L, timeofday_f);
731         return 1;
732 }
733
734 // get_day_count() -> int
735 int ModApiEnvMod::l_get_day_count(lua_State *L)
736 {
737         GET_PLAIN_ENV_PTR;
738
739         lua_pushnumber(L, env->getDayCount());
740         return 1;
741 }
742
743 // get_gametime()
744 int ModApiEnvMod::l_get_gametime(lua_State *L)
745 {
746         GET_ENV_PTR;
747
748         int game_time = env->getGameTime();
749         lua_pushnumber(L, game_time);
750         return 1;
751 }
752
753
754 // find_node_near(pos, radius, nodenames, search_center) -> pos or nil
755 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
756 int ModApiEnvMod::l_find_node_near(lua_State *L)
757 {
758         GET_PLAIN_ENV_PTR;
759
760         const NodeDefManager *ndef = env->getGameDef()->ndef();
761         v3s16 pos = read_v3s16(L, 1);
762         int radius = luaL_checkinteger(L, 2);
763         std::vector<content_t> filter;
764         if (lua_istable(L, 3)) {
765                 lua_pushnil(L);
766                 while (lua_next(L, 3) != 0) {
767                         // key at index -2 and value at index -1
768                         luaL_checktype(L, -1, LUA_TSTRING);
769                         ndef->getIds(readParam<std::string>(L, -1), filter);
770                         // removes value, keeps key for next iteration
771                         lua_pop(L, 1);
772                 }
773         } else if (lua_isstring(L, 3)) {
774                 ndef->getIds(readParam<std::string>(L, 3), filter);
775         }
776
777         int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1;
778
779 #ifndef SERVER
780         // Client API limitations
781         if (getClient(L))
782                 radius = getClient(L)->CSMClampRadius(pos, radius);
783 #endif
784
785         for (int d = start_radius; d <= radius; d++) {
786                 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
787                 for (const v3s16 &i : list) {
788                         v3s16 p = pos + i;
789                         content_t c = env->getMap().getNode(p).getContent();
790                         if (CONTAINS(filter, c)) {
791                                 push_v3s16(L, p);
792                                 return 1;
793                         }
794                 }
795         }
796         return 0;
797 }
798
799 // find_nodes_in_area(minp, maxp, nodenames) -> list of positions
800 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
801 int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
802 {
803         GET_PLAIN_ENV_PTR;
804
805         v3s16 minp = read_v3s16(L, 1);
806         v3s16 maxp = read_v3s16(L, 2);
807         sortBoxVerticies(minp, maxp);
808
809         const NodeDefManager *ndef = env->getGameDef()->ndef();
810
811 #ifndef SERVER
812         if (getClient(L)) {
813                 minp = getClient(L)->CSMClampPos(minp);
814                 maxp = getClient(L)->CSMClampPos(maxp);
815         }
816 #endif
817
818         v3s16 cube = maxp - minp + 1;
819         // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
820         if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
821                 luaL_error(L, "find_nodes_in_area(): area volume"
822                                 " exceeds allowed value of 4096000");
823                 return 0;
824         }
825
826         std::vector<content_t> filter;
827         if (lua_istable(L, 3)) {
828                 lua_pushnil(L);
829                 while (lua_next(L, 3) != 0) {
830                         // key at index -2 and value at index -1
831                         luaL_checktype(L, -1, LUA_TSTRING);
832                         ndef->getIds(readParam<std::string>(L, -1), filter);
833                         // removes value, keeps key for next iteration
834                         lua_pop(L, 1);
835                 }
836         } else if (lua_isstring(L, 3)) {
837                 ndef->getIds(readParam<std::string>(L, 3), filter);
838         }
839
840         std::vector<u32> individual_count;
841         individual_count.resize(filter.size());
842
843         lua_newtable(L);
844         u64 i = 0;
845         for (s16 x = minp.X; x <= maxp.X; x++)
846         for (s16 y = minp.Y; y <= maxp.Y; y++)
847         for (s16 z = minp.Z; z <= maxp.Z; z++) {
848                 v3s16 p(x, y, z);
849                 content_t c = env->getMap().getNode(p).getContent();
850
851                 std::vector<content_t>::iterator it = std::find(filter.begin(), filter.end(), c);
852                 if (it != filter.end()) {
853                         push_v3s16(L, p);
854                         lua_rawseti(L, -2, ++i);
855
856                         u32 filt_index = it - filter.begin();
857                         individual_count[filt_index]++;
858                 }
859         }
860         lua_newtable(L);
861         for (u32 i = 0; i < filter.size(); i++) {
862                 lua_pushnumber(L, individual_count[i]);
863                 lua_setfield(L, -2, ndef->get(filter[i]).name.c_str());
864         }
865         return 2;
866 }
867
868 // find_nodes_in_area_under_air(minp, maxp, nodenames) -> list of positions
869 // nodenames: e.g. {"ignore", "group:tree"} or "default:dirt"
870 int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
871 {
872         /* Note: A similar but generalized (and therefore slower) version of this
873          * function could be created -- e.g. find_nodes_in_area_under -- which
874          * would accept a node name (or ID?) or list of names that the "above node"
875          * should be.
876          * TODO
877          */
878
879         GET_PLAIN_ENV_PTR;
880
881         v3s16 minp = read_v3s16(L, 1);
882         v3s16 maxp = read_v3s16(L, 2);
883         sortBoxVerticies(minp, maxp);
884
885         const NodeDefManager *ndef = env->getGameDef()->ndef();
886
887 #ifndef SERVER
888         if (getClient(L)) {
889                 minp = getClient(L)->CSMClampPos(minp);
890                 maxp = getClient(L)->CSMClampPos(maxp);
891         }
892 #endif
893
894         v3s16 cube = maxp - minp + 1;
895         // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
896         if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
897                 luaL_error(L, "find_nodes_in_area_under_air(): area volume"
898                                 " exceeds allowed value of 4096000");
899                 return 0;
900         }
901
902         std::vector<content_t> filter;
903
904         if (lua_istable(L, 3)) {
905                 lua_pushnil(L);
906                 while (lua_next(L, 3) != 0) {
907                         // key at index -2 and value at index -1
908                         luaL_checktype(L, -1, LUA_TSTRING);
909                         ndef->getIds(readParam<std::string>(L, -1), filter);
910                         // removes value, keeps key for next iteration
911                         lua_pop(L, 1);
912                 }
913         } else if (lua_isstring(L, 3)) {
914                 ndef->getIds(readParam<std::string>(L, 3), filter);
915         }
916
917         lua_newtable(L);
918         u64 i = 0;
919         for (s16 x = minp.X; x <= maxp.X; x++)
920         for (s16 z = minp.Z; z <= maxp.Z; z++) {
921                 s16 y = minp.Y;
922                 v3s16 p(x, y, z);
923                 content_t c = env->getMap().getNode(p).getContent();
924                 for (; y <= maxp.Y; y++) {
925                         v3s16 psurf(x, y + 1, z);
926                         content_t csurf = env->getMap().getNode(psurf).getContent();
927                         if (c != CONTENT_AIR && csurf == CONTENT_AIR &&
928                                         CONTAINS(filter, c)) {
929                                 push_v3s16(L, v3s16(x, y, z));
930                                 lua_rawseti(L, -2, ++i);
931                         }
932                         c = csurf;
933                 }
934         }
935         return 1;
936 }
937
938 // get_perlin(seeddiff, octaves, persistence, scale)
939 // returns world-specific PerlinNoise
940 int ModApiEnvMod::l_get_perlin(lua_State *L)
941 {
942         GET_ENV_PTR_NO_MAP_LOCK;
943
944         NoiseParams params;
945
946         if (lua_istable(L, 1)) {
947                 read_noiseparams(L, 1, &params);
948         } else {
949                 params.seed    = luaL_checkint(L, 1);
950                 params.octaves = luaL_checkint(L, 2);
951                 params.persist = readParam<float>(L, 3);
952                 params.spread  = v3f(1, 1, 1) * readParam<float>(L, 4);
953         }
954
955         params.seed += (int)env->getServerMap().getSeed();
956
957         LuaPerlinNoise *n = new LuaPerlinNoise(&params);
958         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
959         luaL_getmetatable(L, "PerlinNoise");
960         lua_setmetatable(L, -2);
961         return 1;
962 }
963
964 // get_perlin_map(noiseparams, size)
965 // returns world-specific PerlinNoiseMap
966 int ModApiEnvMod::l_get_perlin_map(lua_State *L)
967 {
968         GET_ENV_PTR_NO_MAP_LOCK;
969
970         NoiseParams np;
971         if (!read_noiseparams(L, 1, &np))
972                 return 0;
973         v3s16 size = read_v3s16(L, 2);
974
975         s32 seed = (s32)(env->getServerMap().getSeed());
976         LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(&np, seed, size);
977         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
978         luaL_getmetatable(L, "PerlinNoiseMap");
979         lua_setmetatable(L, -2);
980         return 1;
981 }
982
983 // get_voxel_manip()
984 // returns voxel manipulator
985 int ModApiEnvMod::l_get_voxel_manip(lua_State *L)
986 {
987         GET_ENV_PTR;
988
989         Map *map = &(env->getMap());
990         LuaVoxelManip *o = (lua_istable(L, 1) && lua_istable(L, 2)) ?
991                 new LuaVoxelManip(map, read_v3s16(L, 1), read_v3s16(L, 2)) :
992                 new LuaVoxelManip(map);
993
994         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
995         luaL_getmetatable(L, "VoxelManip");
996         lua_setmetatable(L, -2);
997         return 1;
998 }
999
1000 // clear_objects([options])
1001 // clear all objects in the environment
1002 // where options = {mode = "full" or "quick"}
1003 int ModApiEnvMod::l_clear_objects(lua_State *L)
1004 {
1005         GET_ENV_PTR;
1006
1007         ClearObjectsMode mode = CLEAR_OBJECTS_MODE_QUICK;
1008         if (lua_istable(L, 1)) {
1009                 mode = (ClearObjectsMode)getenumfield(L, 1, "mode",
1010                         ModApiEnvMod::es_ClearObjectsMode, mode);
1011         }
1012
1013         env->clearObjects(mode);
1014         return 0;
1015 }
1016
1017 // line_of_sight(pos1, pos2) -> true/false, pos
1018 int ModApiEnvMod::l_line_of_sight(lua_State *L)
1019 {
1020         GET_PLAIN_ENV_PTR;
1021
1022         // read position 1 from lua
1023         v3f pos1 = checkFloatPos(L, 1);
1024         // read position 2 from lua
1025         v3f pos2 = checkFloatPos(L, 2);
1026
1027         v3s16 p;
1028
1029         bool success = env->line_of_sight(pos1, pos2, &p);
1030         lua_pushboolean(L, success);
1031         if (!success) {
1032                 push_v3s16(L, p);
1033                 return 2;
1034         }
1035         return 1;
1036 }
1037
1038 // fix_light(p1, p2)
1039 int ModApiEnvMod::l_fix_light(lua_State *L)
1040 {
1041         GET_ENV_PTR;
1042
1043         v3s16 blockpos1 = getContainerPos(read_v3s16(L, 1), MAP_BLOCKSIZE);
1044         v3s16 blockpos2 = getContainerPos(read_v3s16(L, 2), MAP_BLOCKSIZE);
1045         ServerMap &map = env->getServerMap();
1046         std::map<v3s16, MapBlock *> modified_blocks;
1047         bool success = true;
1048         v3s16 blockpos;
1049         for (blockpos.X = blockpos1.X; blockpos.X <= blockpos2.X; blockpos.X++)
1050         for (blockpos.Y = blockpos1.Y; blockpos.Y <= blockpos2.Y; blockpos.Y++)
1051         for (blockpos.Z = blockpos1.Z; blockpos.Z <= blockpos2.Z; blockpos.Z++) {
1052                 success = success & map.repairBlockLight(blockpos, &modified_blocks);
1053         }
1054         if (!modified_blocks.empty()) {
1055                 MapEditEvent event;
1056                 event.type = MEET_OTHER;
1057                 for (auto &modified_block : modified_blocks)
1058                         event.modified_blocks.insert(modified_block.first);
1059
1060                 map.dispatchEvent(event);
1061         }
1062         lua_pushboolean(L, success);
1063
1064         return 1;
1065 }
1066
1067 int ModApiEnvMod::l_raycast(lua_State *L)
1068 {
1069         return LuaRaycast::create_object(L);
1070 }
1071
1072 // load_area(p1, [p2])
1073 // load mapblocks in area p1..p2, but do not generate map
1074 int ModApiEnvMod::l_load_area(lua_State *L)
1075 {
1076         GET_ENV_PTR;
1077         MAP_LOCK_REQUIRED;
1078
1079         Map *map = &(env->getMap());
1080         v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 1));
1081         if (!lua_istable(L, 2)) {
1082                 map->emergeBlock(bp1);
1083         } else {
1084                 v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 2));
1085                 sortBoxVerticies(bp1, bp2);
1086                 for (s16 z = bp1.Z; z <= bp2.Z; z++)
1087                 for (s16 y = bp1.Y; y <= bp2.Y; y++)
1088                 for (s16 x = bp1.X; x <= bp2.X; x++) {
1089                         map->emergeBlock(v3s16(x, y, z));
1090                 }
1091         }
1092
1093         return 0;
1094 }
1095
1096 // emerge_area(p1, p2, [callback, context])
1097 // emerge mapblocks in area p1..p2, calls callback with context upon completion
1098 int ModApiEnvMod::l_emerge_area(lua_State *L)
1099 {
1100         GET_ENV_PTR;
1101
1102         EmergeCompletionCallback callback = NULL;
1103         ScriptCallbackState *state = NULL;
1104
1105         EmergeManager *emerge = getServer(L)->getEmergeManager();
1106
1107         v3s16 bpmin = getNodeBlockPos(read_v3s16(L, 1));
1108         v3s16 bpmax = getNodeBlockPos(read_v3s16(L, 2));
1109         sortBoxVerticies(bpmin, bpmax);
1110
1111         size_t num_blocks = VoxelArea(bpmin, bpmax).getVolume();
1112         assert(num_blocks != 0);
1113
1114         if (lua_isfunction(L, 3)) {
1115                 callback = LuaEmergeAreaCallback;
1116
1117                 lua_pushvalue(L, 3);
1118                 int callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1119
1120                 lua_pushvalue(L, 4);
1121                 int args_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1122
1123                 state = new ScriptCallbackState;
1124                 state->script       = getServer(L)->getScriptIface();
1125                 state->callback_ref = callback_ref;
1126                 state->args_ref     = args_ref;
1127                 state->refcount     = num_blocks;
1128                 state->origin       = getScriptApiBase(L)->getOrigin();
1129         }
1130
1131         for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
1132         for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
1133         for (s16 x = bpmin.X; x <= bpmax.X; x++) {
1134                 emerge->enqueueBlockEmergeEx(v3s16(x, y, z), PEER_ID_INEXISTENT,
1135                         BLOCK_EMERGE_ALLOW_GEN | BLOCK_EMERGE_FORCE_QUEUE, callback, state);
1136         }
1137
1138         return 0;
1139 }
1140
1141 // delete_area(p1, p2)
1142 // delete mapblocks in area p1..p2
1143 int ModApiEnvMod::l_delete_area(lua_State *L)
1144 {
1145         GET_ENV_PTR;
1146
1147         v3s16 bpmin = getNodeBlockPos(read_v3s16(L, 1));
1148         v3s16 bpmax = getNodeBlockPos(read_v3s16(L, 2));
1149         sortBoxVerticies(bpmin, bpmax);
1150
1151         ServerMap &map = env->getServerMap();
1152
1153         MapEditEvent event;
1154         event.type = MEET_OTHER;
1155
1156         bool success = true;
1157         for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
1158         for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
1159         for (s16 x = bpmin.X; x <= bpmax.X; x++) {
1160                 v3s16 bp(x, y, z);
1161                 if (map.deleteBlock(bp)) {
1162                         env->setStaticForActiveObjectsInBlock(bp, false);
1163                         event.modified_blocks.insert(bp);
1164                 } else {
1165                         success = false;
1166                 }
1167         }
1168
1169         map.dispatchEvent(event);
1170         lua_pushboolean(L, success);
1171         return 1;
1172 }
1173
1174 // find_path(pos1, pos2, searchdistance,
1175 //     max_jump, max_drop, algorithm) -> table containing path
1176 int ModApiEnvMod::l_find_path(lua_State *L)
1177 {
1178         GET_ENV_PTR;
1179
1180         v3s16 pos1                  = read_v3s16(L, 1);
1181         v3s16 pos2                  = read_v3s16(L, 2);
1182         unsigned int searchdistance = luaL_checkint(L, 3);
1183         unsigned int max_jump       = luaL_checkint(L, 4);
1184         unsigned int max_drop       = luaL_checkint(L, 5);
1185         PathAlgorithm algo          = PA_PLAIN_NP;
1186         if (!lua_isnoneornil(L, 6)) {
1187                 std::string algorithm = luaL_checkstring(L,6);
1188
1189                 if (algorithm == "A*")
1190                         algo = PA_PLAIN;
1191
1192                 if (algorithm == "Dijkstra")
1193                         algo = PA_DIJKSTRA;
1194         }
1195
1196         std::vector<v3s16> path = get_path(env, pos1, pos2,
1197                 searchdistance, max_jump, max_drop, algo);
1198
1199         if (!path.empty()) {
1200                 lua_newtable(L);
1201                 int top = lua_gettop(L);
1202                 unsigned int index = 1;
1203                 for (const v3s16 &i : path) {
1204                         lua_pushnumber(L,index);
1205                         push_v3s16(L, i);
1206                         lua_settable(L, top);
1207                         index++;
1208                 }
1209                 return 1;
1210         }
1211
1212         return 0;
1213 }
1214
1215 // spawn_tree(pos, treedef)
1216 int ModApiEnvMod::l_spawn_tree(lua_State *L)
1217 {
1218         GET_ENV_PTR;
1219
1220         v3s16 p0 = read_v3s16(L, 1);
1221
1222         treegen::TreeDef tree_def;
1223         std::string trunk,leaves,fruit;
1224         const NodeDefManager *ndef = env->getGameDef()->ndef();
1225
1226         if(lua_istable(L, 2))
1227         {
1228                 getstringfield(L, 2, "axiom", tree_def.initial_axiom);
1229                 getstringfield(L, 2, "rules_a", tree_def.rules_a);
1230                 getstringfield(L, 2, "rules_b", tree_def.rules_b);
1231                 getstringfield(L, 2, "rules_c", tree_def.rules_c);
1232                 getstringfield(L, 2, "rules_d", tree_def.rules_d);
1233                 getstringfield(L, 2, "trunk", trunk);
1234                 tree_def.trunknode=ndef->getId(trunk);
1235                 getstringfield(L, 2, "leaves", leaves);
1236                 tree_def.leavesnode=ndef->getId(leaves);
1237                 tree_def.leaves2_chance=0;
1238                 getstringfield(L, 2, "leaves2", leaves);
1239                 if (!leaves.empty()) {
1240                         tree_def.leaves2node=ndef->getId(leaves);
1241                         getintfield(L, 2, "leaves2_chance", tree_def.leaves2_chance);
1242                 }
1243                 getintfield(L, 2, "angle", tree_def.angle);
1244                 getintfield(L, 2, "iterations", tree_def.iterations);
1245                 if (!getintfield(L, 2, "random_level", tree_def.iterations_random_level))
1246                         tree_def.iterations_random_level = 0;
1247                 getstringfield(L, 2, "trunk_type", tree_def.trunk_type);
1248                 getboolfield(L, 2, "thin_branches", tree_def.thin_branches);
1249                 tree_def.fruit_chance=0;
1250                 getstringfield(L, 2, "fruit", fruit);
1251                 if (!fruit.empty()) {
1252                         tree_def.fruitnode=ndef->getId(fruit);
1253                         getintfield(L, 2, "fruit_chance",tree_def.fruit_chance);
1254                 }
1255                 tree_def.explicit_seed = getintfield(L, 2, "seed", tree_def.seed);
1256         }
1257         else
1258                 return 0;
1259
1260         treegen::error e;
1261         if ((e = treegen::spawn_ltree (env, p0, ndef, tree_def)) != treegen::SUCCESS) {
1262                 if (e == treegen::UNBALANCED_BRACKETS) {
1263                         luaL_error(L, "spawn_tree(): closing ']' has no matching opening bracket");
1264                 } else {
1265                         luaL_error(L, "spawn_tree(): unknown error");
1266                 }
1267         }
1268
1269         return 1;
1270 }
1271
1272 // transforming_liquid_add(pos)
1273 int ModApiEnvMod::l_transforming_liquid_add(lua_State *L)
1274 {
1275         GET_ENV_PTR;
1276
1277         v3s16 p0 = read_v3s16(L, 1);
1278         env->getMap().transforming_liquid_add(p0);
1279         return 1;
1280 }
1281
1282 // forceload_block(blockpos)
1283 // blockpos = {x=num, y=num, z=num}
1284 int ModApiEnvMod::l_forceload_block(lua_State *L)
1285 {
1286         GET_ENV_PTR;
1287
1288         v3s16 blockpos = read_v3s16(L, 1);
1289         env->getForceloadedBlocks()->insert(blockpos);
1290         return 0;
1291 }
1292
1293 // forceload_free_block(blockpos)
1294 // blockpos = {x=num, y=num, z=num}
1295 int ModApiEnvMod::l_forceload_free_block(lua_State *L)
1296 {
1297         GET_ENV_PTR;
1298
1299         v3s16 blockpos = read_v3s16(L, 1);
1300         env->getForceloadedBlocks()->erase(blockpos);
1301         return 0;
1302 }
1303
1304 void ModApiEnvMod::Initialize(lua_State *L, int top)
1305 {
1306         API_FCT(set_node);
1307         API_FCT(bulk_set_node);
1308         API_FCT(add_node);
1309         API_FCT(swap_node);
1310         API_FCT(add_item);
1311         API_FCT(remove_node);
1312         API_FCT(get_node);
1313         API_FCT(get_node_or_nil);
1314         API_FCT(get_node_light);
1315         API_FCT(place_node);
1316         API_FCT(dig_node);
1317         API_FCT(punch_node);
1318         API_FCT(get_node_max_level);
1319         API_FCT(get_node_level);
1320         API_FCT(set_node_level);
1321         API_FCT(add_node_level);
1322         API_FCT(add_entity);
1323         API_FCT(find_nodes_with_meta);
1324         API_FCT(get_meta);
1325         API_FCT(get_node_timer);
1326         API_FCT(get_connected_players);
1327         API_FCT(get_player_by_name);
1328         API_FCT(get_objects_inside_radius);
1329         API_FCT(set_timeofday);
1330         API_FCT(get_timeofday);
1331         API_FCT(get_gametime);
1332         API_FCT(get_day_count);
1333         API_FCT(find_node_near);
1334         API_FCT(find_nodes_in_area);
1335         API_FCT(find_nodes_in_area_under_air);
1336         API_FCT(fix_light);
1337         API_FCT(load_area);
1338         API_FCT(emerge_area);
1339         API_FCT(delete_area);
1340         API_FCT(get_perlin);
1341         API_FCT(get_perlin_map);
1342         API_FCT(get_voxel_manip);
1343         API_FCT(clear_objects);
1344         API_FCT(spawn_tree);
1345         API_FCT(find_path);
1346         API_FCT(line_of_sight);
1347         API_FCT(raycast);
1348         API_FCT(transforming_liquid_add);
1349         API_FCT(forceload_block);
1350         API_FCT(forceload_free_block);
1351 }
1352
1353 void ModApiEnvMod::InitializeClient(lua_State *L, int top)
1354 {
1355         API_FCT(get_node_light);
1356         API_FCT(get_timeofday);
1357         API_FCT(get_node_max_level);
1358         API_FCT(get_node_level);
1359         API_FCT(find_nodes_with_meta);
1360         API_FCT(find_node_near);
1361         API_FCT(find_nodes_in_area);
1362         API_FCT(find_nodes_in_area_under_air);
1363         API_FCT(line_of_sight);
1364         API_FCT(raycast);
1365 }