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