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