Predict param2 of facedir nodes and attachment of attached_node nodes
[oweals/minetest.git] / src / scriptapi_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 "scriptapi.h"
21 #include "scriptapi_env.h"
22 #include "nodedef.h"
23 #include "gamedef.h"
24 #include "map.h"
25 #include "daynightratio.h"
26 #include "content_sao.h"
27 #include "script.h"
28 #include "treegen.h"
29 #include "pathfinder.h"
30 #include "util/pointedthing.h"
31 #include "scriptapi_types.h"
32 #include "scriptapi_noise.h"
33 #include "scriptapi_nodemeta.h"
34 #include "scriptapi_nodetimer.h"
35 #include "scriptapi_object.h"
36 #include "scriptapi_common.h"
37 #include "scriptapi_item.h"
38 #include "scriptapi_node.h"
39
40
41 //TODO
42 extern void scriptapi_run_callbacks(lua_State *L, int nargs,
43                 RunCallbacksMode mode);
44
45
46 class LuaABM : public ActiveBlockModifier
47 {
48 private:
49         lua_State *m_lua;
50         int m_id;
51
52         std::set<std::string> m_trigger_contents;
53         std::set<std::string> m_required_neighbors;
54         float m_trigger_interval;
55         u32 m_trigger_chance;
56 public:
57         LuaABM(lua_State *L, int id,
58                         const std::set<std::string> &trigger_contents,
59                         const std::set<std::string> &required_neighbors,
60                         float trigger_interval, u32 trigger_chance):
61                 m_lua(L),
62                 m_id(id),
63                 m_trigger_contents(trigger_contents),
64                 m_required_neighbors(required_neighbors),
65                 m_trigger_interval(trigger_interval),
66                 m_trigger_chance(trigger_chance)
67         {
68         }
69         virtual std::set<std::string> getTriggerContents()
70         {
71                 return m_trigger_contents;
72         }
73         virtual std::set<std::string> getRequiredNeighbors()
74         {
75                 return m_required_neighbors;
76         }
77         virtual float getTriggerInterval()
78         {
79                 return m_trigger_interval;
80         }
81         virtual u32 getTriggerChance()
82         {
83                 return m_trigger_chance;
84         }
85         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
86                         u32 active_object_count, u32 active_object_count_wider)
87         {
88                 lua_State *L = m_lua;
89
90                 realitycheck(L);
91                 assert(lua_checkstack(L, 20));
92                 StackUnroller stack_unroller(L);
93
94                 // Get minetest.registered_abms
95                 lua_getglobal(L, "minetest");
96                 lua_getfield(L, -1, "registered_abms");
97                 luaL_checktype(L, -1, LUA_TTABLE);
98                 int registered_abms = lua_gettop(L);
99
100                 // Get minetest.registered_abms[m_id]
101                 lua_pushnumber(L, m_id);
102                 lua_gettable(L, registered_abms);
103                 if(lua_isnil(L, -1))
104                         assert(0);
105
106                 // Call action
107                 luaL_checktype(L, -1, LUA_TTABLE);
108                 lua_getfield(L, -1, "action");
109                 luaL_checktype(L, -1, LUA_TFUNCTION);
110                 push_v3s16(L, p);
111                 pushnode(L, n, env->getGameDef()->ndef());
112                 lua_pushnumber(L, active_object_count);
113                 lua_pushnumber(L, active_object_count_wider);
114                 if(lua_pcall(L, 4, 0, 0))
115                         script_error(L, "error: %s", lua_tostring(L, -1));
116         }
117 };
118
119 /*
120         EnvRef
121 */
122
123 int EnvRef::gc_object(lua_State *L) {
124         EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
125         delete o;
126         return 0;
127 }
128
129 EnvRef* EnvRef::checkobject(lua_State *L, int narg)
130 {
131         luaL_checktype(L, narg, LUA_TUSERDATA);
132         void *ud = luaL_checkudata(L, narg, className);
133         if(!ud) luaL_typerror(L, narg, className);
134         return *(EnvRef**)ud;  // unbox pointer
135 }
136
137 // Exported functions
138
139 // EnvRef:set_node(pos, node)
140 // pos = {x=num, y=num, z=num}
141 int EnvRef::l_set_node(lua_State *L)
142 {
143         EnvRef *o = checkobject(L, 1);
144         ServerEnvironment *env = o->m_env;
145         if(env == NULL) return 0;
146         INodeDefManager *ndef = env->getGameDef()->ndef();
147         // parameters
148         v3s16 pos = read_v3s16(L, 2);
149         MapNode n = readnode(L, 3, ndef);
150         // Do it
151         bool succeeded = env->setNode(pos, n);
152         lua_pushboolean(L, succeeded);
153         return 1;
154 }
155
156 int EnvRef::l_add_node(lua_State *L)
157 {
158         return l_set_node(L);
159 }
160
161 // EnvRef:remove_node(pos)
162 // pos = {x=num, y=num, z=num}
163 int EnvRef::l_remove_node(lua_State *L)
164 {
165         EnvRef *o = checkobject(L, 1);
166         ServerEnvironment *env = o->m_env;
167         if(env == NULL) return 0;
168
169         // parameters
170         v3s16 pos = read_v3s16(L, 2);
171         // Do it
172         bool succeeded = env->removeNode(pos);
173         lua_pushboolean(L, succeeded);
174         return 1;
175 }
176
177 // EnvRef:get_node(pos)
178 // pos = {x=num, y=num, z=num}
179 int EnvRef::l_get_node(lua_State *L)
180 {
181         EnvRef *o = checkobject(L, 1);
182         ServerEnvironment *env = o->m_env;
183         if(env == NULL) return 0;
184         // pos
185         v3s16 pos = read_v3s16(L, 2);
186         // Do it
187         MapNode n = env->getMap().getNodeNoEx(pos);
188         // Return node
189         pushnode(L, n, env->getGameDef()->ndef());
190         return 1;
191 }
192
193 // EnvRef:get_node_or_nil(pos)
194 // pos = {x=num, y=num, z=num}
195 int EnvRef::l_get_node_or_nil(lua_State *L)
196 {
197         EnvRef *o = checkobject(L, 1);
198         ServerEnvironment *env = o->m_env;
199         if(env == NULL) return 0;
200         // pos
201         v3s16 pos = read_v3s16(L, 2);
202         // Do it
203         try{
204                 MapNode n = env->getMap().getNode(pos);
205                 // Return node
206                 pushnode(L, n, env->getGameDef()->ndef());
207                 return 1;
208         } catch(InvalidPositionException &e)
209         {
210                 lua_pushnil(L);
211                 return 1;
212         }
213 }
214
215 // EnvRef:get_node_light(pos, timeofday)
216 // pos = {x=num, y=num, z=num}
217 // timeofday: nil = current time, 0 = night, 0.5 = day
218 int EnvRef::l_get_node_light(lua_State *L)
219 {
220         EnvRef *o = checkobject(L, 1);
221         ServerEnvironment *env = o->m_env;
222         if(env == NULL) return 0;
223         // Do it
224         v3s16 pos = read_v3s16(L, 2);
225         u32 time_of_day = env->getTimeOfDay();
226         if(lua_isnumber(L, 3))
227                 time_of_day = 24000.0 * lua_tonumber(L, 3);
228         time_of_day %= 24000;
229         u32 dnr = time_to_daynight_ratio(time_of_day, true);
230         try{
231                 MapNode n = env->getMap().getNode(pos);
232                 INodeDefManager *ndef = env->getGameDef()->ndef();
233                 lua_pushinteger(L, n.getLightBlend(dnr, ndef));
234                 return 1;
235         } catch(InvalidPositionException &e)
236         {
237                 lua_pushnil(L);
238                 return 1;
239         }
240 }
241
242 // EnvRef:place_node(pos, node)
243 // pos = {x=num, y=num, z=num}
244 int EnvRef::l_place_node(lua_State *L)
245 {
246         EnvRef *o = checkobject(L, 1);
247         ServerEnvironment *env = o->m_env;
248         if(env == NULL) return 0;
249         v3s16 pos = read_v3s16(L, 2);
250         MapNode n = readnode(L, 3, env->getGameDef()->ndef());
251
252         // Don't attempt to load non-loaded area as of now
253         MapNode n_old = env->getMap().getNodeNoEx(pos);
254         if(n_old.getContent() == CONTENT_IGNORE){
255                 lua_pushboolean(L, false);
256                 return 1;
257         }
258         // Create item to place
259         INodeDefManager *ndef = get_server(L)->ndef();
260         IItemDefManager *idef = get_server(L)->idef();
261         ItemStack item(ndef->get(n).name, 1, 0, "", idef);
262         // Make pointed position
263         PointedThing pointed;
264         pointed.type = POINTEDTHING_NODE;
265         pointed.node_abovesurface = pos;
266         pointed.node_undersurface = pos + v3s16(0,-1,0);
267         // Place it with a NULL placer (appears in Lua as a non-functional
268         // ObjectRef)
269         bool success = scriptapi_item_on_place(L, item, NULL, pointed);
270         lua_pushboolean(L, success);
271         return 1;
272 }
273
274 // EnvRef:dig_node(pos)
275 // pos = {x=num, y=num, z=num}
276 int EnvRef::l_dig_node(lua_State *L)
277 {
278         EnvRef *o = checkobject(L, 1);
279         ServerEnvironment *env = o->m_env;
280         if(env == NULL) return 0;
281         v3s16 pos = read_v3s16(L, 2);
282
283         // Don't attempt to load non-loaded area as of now
284         MapNode n = env->getMap().getNodeNoEx(pos);
285         if(n.getContent() == CONTENT_IGNORE){
286                 lua_pushboolean(L, false);
287                 return 1;
288         }
289         // Dig it out with a NULL digger (appears in Lua as a
290         // non-functional ObjectRef)
291         bool success = scriptapi_node_on_dig(L, pos, n, NULL);
292         lua_pushboolean(L, success);
293         return 1;
294 }
295
296 // EnvRef:punch_node(pos)
297 // pos = {x=num, y=num, z=num}
298 int EnvRef::l_punch_node(lua_State *L)
299 {
300         EnvRef *o = checkobject(L, 1);
301         ServerEnvironment *env = o->m_env;
302         if(env == NULL) return 0;
303         v3s16 pos = read_v3s16(L, 2);
304
305         // Don't attempt to load non-loaded area as of now
306         MapNode n = env->getMap().getNodeNoEx(pos);
307         if(n.getContent() == CONTENT_IGNORE){
308                 lua_pushboolean(L, false);
309                 return 1;
310         }
311         // Punch it with a NULL puncher (appears in Lua as a non-functional
312         // ObjectRef)
313         bool success = scriptapi_node_on_punch(L, pos, n, NULL);
314         lua_pushboolean(L, success);
315         return 1;
316 }
317
318 // EnvRef:get_meta(pos)
319 int EnvRef::l_get_meta(lua_State *L)
320 {
321         //infostream<<"EnvRef::l_get_meta()"<<std::endl;
322         EnvRef *o = checkobject(L, 1);
323         ServerEnvironment *env = o->m_env;
324         if(env == NULL) return 0;
325         // Do it
326         v3s16 p = read_v3s16(L, 2);
327         NodeMetaRef::create(L, p, env);
328         return 1;
329 }
330
331 // EnvRef:get_node_timer(pos)
332 int EnvRef::l_get_node_timer(lua_State *L)
333 {
334         EnvRef *o = checkobject(L, 1);
335         ServerEnvironment *env = o->m_env;
336         if(env == NULL) return 0;
337         // Do it
338         v3s16 p = read_v3s16(L, 2);
339         NodeTimerRef::create(L, p, env);
340         return 1;
341 }
342
343 // EnvRef:add_entity(pos, entityname) -> ObjectRef or nil
344 // pos = {x=num, y=num, z=num}
345 int EnvRef::l_add_entity(lua_State *L)
346 {
347         //infostream<<"EnvRef::l_add_entity()"<<std::endl;
348         EnvRef *o = checkobject(L, 1);
349         ServerEnvironment *env = o->m_env;
350         if(env == NULL) return 0;
351         // pos
352         v3f pos = checkFloatPos(L, 2);
353         // content
354         const char *name = luaL_checkstring(L, 3);
355         // Do it
356         ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
357         int objectid = env->addActiveObject(obj);
358         // If failed to add, return nothing (reads as nil)
359         if(objectid == 0)
360                 return 0;
361         // Return ObjectRef
362         objectref_get_or_create(L, obj);
363         return 1;
364 }
365
366 // EnvRef:add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil
367 // pos = {x=num, y=num, z=num}
368 int EnvRef::l_add_item(lua_State *L)
369 {
370         //infostream<<"EnvRef::l_add_item()"<<std::endl;
371         EnvRef *o = checkobject(L, 1);
372         ServerEnvironment *env = o->m_env;
373         if(env == NULL) return 0;
374         // pos
375         //v3f pos = checkFloatPos(L, 2);
376         // item
377         ItemStack item = read_item(L, 3);
378         if(item.empty() || !item.isKnown(get_server(L)->idef()))
379                 return 0;
380         // Use minetest.spawn_item to spawn a __builtin:item
381         lua_getglobal(L, "minetest");
382         lua_getfield(L, -1, "spawn_item");
383         if(lua_isnil(L, -1))
384                 return 0;
385         lua_pushvalue(L, 2);
386         lua_pushstring(L, item.getItemString().c_str());
387         if(lua_pcall(L, 2, 1, 0))
388                 script_error(L, "error: %s", lua_tostring(L, -1));
389         return 1;
390         /*lua_pushvalue(L, 1);
391         lua_pushstring(L, "__builtin:item");
392         lua_pushstring(L, item.getItemString().c_str());
393         return l_add_entity(L);*/
394         /*// Do it
395         ServerActiveObject *obj = createItemSAO(env, pos, item.getItemString());
396         int objectid = env->addActiveObject(obj);
397         // If failed to add, return nothing (reads as nil)
398         if(objectid == 0)
399                 return 0;
400         // Return ObjectRef
401         objectref_get_or_create(L, obj);
402         return 1;*/
403 }
404
405 // EnvRef:add_rat(pos)
406 // pos = {x=num, y=num, z=num}
407 int EnvRef::l_add_rat(lua_State *L)
408 {
409         infostream<<"EnvRef::l_add_rat(): C++ mobs have been removed."
410                         <<" Doing nothing."<<std::endl;
411         return 0;
412 }
413
414 // EnvRef:add_firefly(pos)
415 // pos = {x=num, y=num, z=num}
416 int EnvRef::l_add_firefly(lua_State *L)
417 {
418         infostream<<"EnvRef::l_add_firefly(): C++ mobs have been removed."
419                         <<" Doing nothing."<<std::endl;
420         return 0;
421 }
422
423 // EnvRef:get_player_by_name(name)
424 int EnvRef::l_get_player_by_name(lua_State *L)
425 {
426         EnvRef *o = checkobject(L, 1);
427         ServerEnvironment *env = o->m_env;
428         if(env == NULL) return 0;
429         // Do it
430         const char *name = luaL_checkstring(L, 2);
431         Player *player = env->getPlayer(name);
432         if(player == NULL){
433                 lua_pushnil(L);
434                 return 1;
435         }
436         PlayerSAO *sao = player->getPlayerSAO();
437         if(sao == NULL){
438                 lua_pushnil(L);
439                 return 1;
440         }
441         // Put player on stack
442         objectref_get_or_create(L, sao);
443         return 1;
444 }
445
446 // EnvRef:get_objects_inside_radius(pos, radius)
447 int EnvRef::l_get_objects_inside_radius(lua_State *L)
448 {
449         // Get the table insert function
450         lua_getglobal(L, "table");
451         lua_getfield(L, -1, "insert");
452         int table_insert = lua_gettop(L);
453         // Get environemnt
454         EnvRef *o = checkobject(L, 1);
455         ServerEnvironment *env = o->m_env;
456         if(env == NULL) return 0;
457         // Do it
458         v3f pos = checkFloatPos(L, 2);
459         float radius = luaL_checknumber(L, 3) * BS;
460         std::set<u16> ids = env->getObjectsInsideRadius(pos, radius);
461         lua_newtable(L);
462         int table = lua_gettop(L);
463         for(std::set<u16>::const_iterator
464                         i = ids.begin(); i != ids.end(); i++){
465                 ServerActiveObject *obj = env->getActiveObject(*i);
466                 // Insert object reference into table
467                 lua_pushvalue(L, table_insert);
468                 lua_pushvalue(L, table);
469                 objectref_get_or_create(L, obj);
470                 if(lua_pcall(L, 2, 0, 0))
471                         script_error(L, "error: %s", lua_tostring(L, -1));
472         }
473         return 1;
474 }
475
476 // EnvRef:set_timeofday(val)
477 // val = 0...1
478 int EnvRef::l_set_timeofday(lua_State *L)
479 {
480         EnvRef *o = checkobject(L, 1);
481         ServerEnvironment *env = o->m_env;
482         if(env == NULL) return 0;
483         // Do it
484         float timeofday_f = luaL_checknumber(L, 2);
485         assert(timeofday_f >= 0.0 && timeofday_f <= 1.0);
486         int timeofday_mh = (int)(timeofday_f * 24000.0);
487         // This should be set directly in the environment but currently
488         // such changes aren't immediately sent to the clients, so call
489         // the server instead.
490         //env->setTimeOfDay(timeofday_mh);
491         get_server(L)->setTimeOfDay(timeofday_mh);
492         return 0;
493 }
494
495 // EnvRef:get_timeofday() -> 0...1
496 int EnvRef::l_get_timeofday(lua_State *L)
497 {
498         EnvRef *o = checkobject(L, 1);
499         ServerEnvironment *env = o->m_env;
500         if(env == NULL) return 0;
501         // Do it
502         int timeofday_mh = env->getTimeOfDay();
503         float timeofday_f = (float)timeofday_mh / 24000.0;
504         lua_pushnumber(L, timeofday_f);
505         return 1;
506 }
507
508
509 // EnvRef:find_node_near(pos, radius, nodenames) -> pos or nil
510 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
511 int EnvRef::l_find_node_near(lua_State *L)
512 {
513         EnvRef *o = checkobject(L, 1);
514         ServerEnvironment *env = o->m_env;
515         if(env == NULL) return 0;
516         INodeDefManager *ndef = get_server(L)->ndef();
517         v3s16 pos = read_v3s16(L, 2);
518         int radius = luaL_checkinteger(L, 3);
519         std::set<content_t> filter;
520         if(lua_istable(L, 4)){
521                 int table = 4;
522                 lua_pushnil(L);
523                 while(lua_next(L, table) != 0){
524                         // key at index -2 and value at index -1
525                         luaL_checktype(L, -1, LUA_TSTRING);
526                         ndef->getIds(lua_tostring(L, -1), filter);
527                         // removes value, keeps key for next iteration
528                         lua_pop(L, 1);
529                 }
530         } else if(lua_isstring(L, 4)){
531                 ndef->getIds(lua_tostring(L, 4), filter);
532         }
533
534         for(int d=1; d<=radius; d++){
535                 std::list<v3s16> list;
536                 getFacePositions(list, d);
537                 for(std::list<v3s16>::iterator i = list.begin();
538                                 i != list.end(); ++i){
539                         v3s16 p = pos + (*i);
540                         content_t c = env->getMap().getNodeNoEx(p).getContent();
541                         if(filter.count(c) != 0){
542                                 push_v3s16(L, p);
543                                 return 1;
544                         }
545                 }
546         }
547         return 0;
548 }
549
550 // EnvRef:find_nodes_in_area(minp, maxp, nodenames) -> list of positions
551 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
552 int EnvRef::l_find_nodes_in_area(lua_State *L)
553 {
554         EnvRef *o = checkobject(L, 1);
555         ServerEnvironment *env = o->m_env;
556         if(env == NULL) return 0;
557         INodeDefManager *ndef = get_server(L)->ndef();
558         v3s16 minp = read_v3s16(L, 2);
559         v3s16 maxp = read_v3s16(L, 3);
560         std::set<content_t> filter;
561         if(lua_istable(L, 4)){
562                 int table = 4;
563                 lua_pushnil(L);
564                 while(lua_next(L, table) != 0){
565                         // key at index -2 and value at index -1
566                         luaL_checktype(L, -1, LUA_TSTRING);
567                         ndef->getIds(lua_tostring(L, -1), filter);
568                         // removes value, keeps key for next iteration
569                         lua_pop(L, 1);
570                 }
571         } else if(lua_isstring(L, 4)){
572                 ndef->getIds(lua_tostring(L, 4), filter);
573         }
574
575         // Get the table insert function
576         lua_getglobal(L, "table");
577         lua_getfield(L, -1, "insert");
578         int table_insert = lua_gettop(L);
579
580         lua_newtable(L);
581         int table = lua_gettop(L);
582         for(s16 x=minp.X; x<=maxp.X; x++)
583         for(s16 y=minp.Y; y<=maxp.Y; y++)
584         for(s16 z=minp.Z; z<=maxp.Z; z++)
585         {
586                 v3s16 p(x,y,z);
587                 content_t c = env->getMap().getNodeNoEx(p).getContent();
588                 if(filter.count(c) != 0){
589                         lua_pushvalue(L, table_insert);
590                         lua_pushvalue(L, table);
591                         push_v3s16(L, p);
592                         if(lua_pcall(L, 2, 0, 0))
593                                 script_error(L, "error: %s", lua_tostring(L, -1));
594                 }
595         }
596         return 1;
597 }
598
599 //      EnvRef:get_perlin(seeddiff, octaves, persistence, scale)
600 //  returns world-specific PerlinNoise
601 int EnvRef::l_get_perlin(lua_State *L)
602 {
603         EnvRef *o = checkobject(L, 1);
604         ServerEnvironment *env = o->m_env;
605         if(env == NULL) return 0;
606
607         int seeddiff = luaL_checkint(L, 2);
608         int octaves = luaL_checkint(L, 3);
609         float persistence = luaL_checknumber(L, 4);
610         float scale = luaL_checknumber(L, 5);
611
612         LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale);
613         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
614         luaL_getmetatable(L, "PerlinNoise");
615         lua_setmetatable(L, -2);
616         return 1;
617 }
618
619 //  EnvRef:get_perlin_map(noiseparams, size)
620 //  returns world-specific PerlinNoiseMap
621 int EnvRef::l_get_perlin_map(lua_State *L)
622 {
623         EnvRef *o = checkobject(L, 1);
624         ServerEnvironment *env = o->m_env;
625         if (env == NULL)
626                 return 0;
627
628         NoiseParams *np = read_noiseparams(L, 2);
629         if (!np)
630                 return 0;
631         v3s16 size = read_v3s16(L, 3);
632
633         int seed = (int)(env->getServerMap().getSeed());
634         LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(np, seed, size);
635         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
636         luaL_getmetatable(L, "PerlinNoiseMap");
637         lua_setmetatable(L, -2);
638         return 1;
639 }
640
641 // EnvRef:clear_objects()
642 // clear all objects in the environment
643 int EnvRef::l_clear_objects(lua_State *L)
644 {
645         EnvRef *o = checkobject(L, 1);
646         o->m_env->clearAllObjects();
647         return 0;
648 }
649
650 int EnvRef::l_line_of_sight(lua_State *L) {
651         float stepsize = 1.0;
652
653         //infostream<<"EnvRef::l_get_node()"<<std::endl;
654         EnvRef *o = checkobject(L, 1);
655         ServerEnvironment *env = o->m_env;
656         if(env == NULL) return 0;
657
658         // read position 1 from lua
659         v3f pos1 = checkFloatPos(L, 2);
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         lua_pushboolean(L, env->line_of_sight(pos1,pos2,stepsize));
667
668         return 1;
669 }
670
671 int EnvRef::l_find_path(lua_State *L)
672 {
673         EnvRef *o = checkobject(L, 1);
674         ServerEnvironment *env = o->m_env;
675
676         if(env == NULL) return 0;
677
678         v3s16 pos1                  = read_v3s16(L, 2);
679         v3s16 pos2                  = read_v3s16(L, 3);
680         unsigned int searchdistance = luaL_checkint(L, 4);
681         unsigned int max_jump       = luaL_checkint(L, 5);
682         unsigned int max_drop       = luaL_checkint(L, 6);
683         algorithm algo              = A_PLAIN_NP;
684         if(! lua_isnil(L, 7)) {
685                 std::string algorithm       = luaL_checkstring(L,7);
686
687                 if (algorithm == "A*")
688                         algo = A_PLAIN;
689
690                 if (algorithm == "Dijkstra")
691                         algo = DIJKSTRA;
692         }
693
694         std::vector<v3s16> path =
695                         get_Path(env,pos1,pos2,searchdistance,max_jump,max_drop,algo);
696
697         if (path.size() > 0)
698         {
699                 lua_newtable(L);
700                 int top = lua_gettop(L);
701                 unsigned int index = 1;
702                 for (std::vector<v3s16>::iterator i = path.begin(); i != path.end();i++)
703                 {
704                         lua_pushnumber(L,index);
705                         push_v3s16(L, *i);
706                         lua_settable(L, top);
707                         index++;
708                 }
709                 return 1;
710         }
711
712         return 0;
713 }
714
715 int EnvRef::l_spawn_tree(lua_State *L)
716 {
717         EnvRef *o = checkobject(L, 1);
718         ServerEnvironment *env = o->m_env;
719         if(env == NULL) return 0;
720         v3s16 p0 = read_v3s16(L, 2);
721
722         treegen::TreeDef tree_def;
723         std::string trunk,leaves,fruit;
724         INodeDefManager *ndef = env->getGameDef()->ndef();
725
726         if(lua_istable(L, 3))
727         {
728                 getstringfield(L, 3, "axiom", tree_def.initial_axiom);
729                 getstringfield(L, 3, "rules_a", tree_def.rules_a);
730                 getstringfield(L, 3, "rules_b", tree_def.rules_b);
731                 getstringfield(L, 3, "rules_c", tree_def.rules_c);
732                 getstringfield(L, 3, "rules_d", tree_def.rules_d);
733                 getstringfield(L, 3, "trunk", trunk);
734                 tree_def.trunknode=ndef->getId(trunk);
735                 getstringfield(L, 3, "leaves", leaves);
736                 tree_def.leavesnode=ndef->getId(leaves);
737                 tree_def.leaves2_chance=0;
738                 getstringfield(L, 3, "leaves2", leaves);
739                 if (leaves !="")
740                 {
741                         tree_def.leaves2node=ndef->getId(leaves);
742                         getintfield(L, 3, "leaves2_chance", tree_def.leaves2_chance);
743                 }
744                 getintfield(L, 3, "angle", tree_def.angle);
745                 getintfield(L, 3, "iterations", tree_def.iterations);
746                 getintfield(L, 3, "random_level", tree_def.iterations_random_level);
747                 getstringfield(L, 3, "trunk_type", tree_def.trunk_type);
748                 getboolfield(L, 3, "thin_branches", tree_def.thin_branches);
749                 tree_def.fruit_chance=0;
750                 getstringfield(L, 3, "fruit", fruit);
751                 if (fruit != "")
752                 {
753                         tree_def.fruitnode=ndef->getId(fruit);
754                         getintfield(L, 3, "fruit_chance",tree_def.fruit_chance);
755                 }
756                 getintfield(L, 3, "seed", tree_def.seed);
757         }
758         else
759                 return 0;
760         treegen::spawn_ltree (env, p0, ndef, tree_def);
761         return 1;
762 }
763
764
765 EnvRef::EnvRef(ServerEnvironment *env):
766         m_env(env)
767 {
768         //infostream<<"EnvRef created"<<std::endl;
769 }
770
771 EnvRef::~EnvRef()
772 {
773         //infostream<<"EnvRef destructing"<<std::endl;
774 }
775
776 // Creates an EnvRef and leaves it on top of stack
777 // Not callable from Lua; all references are created on the C side.
778 void EnvRef::create(lua_State *L, ServerEnvironment *env)
779 {
780         EnvRef *o = new EnvRef(env);
781         //infostream<<"EnvRef::create: o="<<o<<std::endl;
782         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
783         luaL_getmetatable(L, className);
784         lua_setmetatable(L, -2);
785 }
786
787 void EnvRef::set_null(lua_State *L)
788 {
789         EnvRef *o = checkobject(L, -1);
790         o->m_env = NULL;
791 }
792
793 void EnvRef::Register(lua_State *L)
794 {
795         lua_newtable(L);
796         int methodtable = lua_gettop(L);
797         luaL_newmetatable(L, className);
798         int metatable = lua_gettop(L);
799
800         lua_pushliteral(L, "__metatable");
801         lua_pushvalue(L, methodtable);
802         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
803
804         lua_pushliteral(L, "__index");
805         lua_pushvalue(L, methodtable);
806         lua_settable(L, metatable);
807
808         lua_pushliteral(L, "__gc");
809         lua_pushcfunction(L, gc_object);
810         lua_settable(L, metatable);
811
812         lua_pop(L, 1);  // drop metatable
813
814         luaL_openlib(L, 0, methods, 0);  // fill methodtable
815         lua_pop(L, 1);  // drop methodtable
816
817         // Cannot be created from Lua
818         //lua_register(L, className, create_object);
819 }
820
821 const char EnvRef::className[] = "EnvRef";
822 const luaL_reg EnvRef::methods[] = {
823         luamethod(EnvRef, set_node),
824         luamethod(EnvRef, add_node),
825         luamethod(EnvRef, remove_node),
826         luamethod(EnvRef, get_node),
827         luamethod(EnvRef, get_node_or_nil),
828         luamethod(EnvRef, get_node_light),
829         luamethod(EnvRef, place_node),
830         luamethod(EnvRef, dig_node),
831         luamethod(EnvRef, punch_node),
832         luamethod(EnvRef, add_entity),
833         luamethod(EnvRef, add_item),
834         luamethod(EnvRef, add_rat),
835         luamethod(EnvRef, add_firefly),
836         luamethod(EnvRef, get_meta),
837         luamethod(EnvRef, get_node_timer),
838         luamethod(EnvRef, get_player_by_name),
839         luamethod(EnvRef, get_objects_inside_radius),
840         luamethod(EnvRef, set_timeofday),
841         luamethod(EnvRef, get_timeofday),
842         luamethod(EnvRef, find_node_near),
843         luamethod(EnvRef, find_nodes_in_area),
844         luamethod(EnvRef, get_perlin),
845         luamethod(EnvRef, get_perlin_map),
846         luamethod(EnvRef, clear_objects),
847         luamethod(EnvRef, spawn_tree),
848         luamethod(EnvRef, line_of_sight),
849         luamethod(EnvRef, find_path),
850         {0,0}
851 };
852
853 void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp,
854                 u32 blockseed)
855 {
856         realitycheck(L);
857         assert(lua_checkstack(L, 20));
858         //infostream<<"scriptapi_environment_on_generated"<<std::endl;
859         StackUnroller stack_unroller(L);
860
861         // Get minetest.registered_on_generateds
862         lua_getglobal(L, "minetest");
863         lua_getfield(L, -1, "registered_on_generateds");
864         // Call callbacks
865         push_v3s16(L, minp);
866         push_v3s16(L, maxp);
867         lua_pushnumber(L, blockseed);
868         scriptapi_run_callbacks(L, 3, RUN_CALLBACKS_MODE_FIRST);
869 }
870
871 void scriptapi_environment_step(lua_State *L, float dtime)
872 {
873         realitycheck(L);
874         assert(lua_checkstack(L, 20));
875         //infostream<<"scriptapi_environment_step"<<std::endl;
876         StackUnroller stack_unroller(L);
877
878         // Get minetest.registered_globalsteps
879         lua_getglobal(L, "minetest");
880         lua_getfield(L, -1, "registered_globalsteps");
881         // Call callbacks
882         lua_pushnumber(L, dtime);
883         scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
884 }
885
886 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
887 {
888         realitycheck(L);
889         assert(lua_checkstack(L, 20));
890         verbosestream<<"scriptapi_add_environment"<<std::endl;
891         StackUnroller stack_unroller(L);
892
893         // Create EnvRef on stack
894         EnvRef::create(L, env);
895         int envref = lua_gettop(L);
896
897         // minetest.env = envref
898         lua_getglobal(L, "minetest");
899         luaL_checktype(L, -1, LUA_TTABLE);
900         lua_pushvalue(L, envref);
901         lua_setfield(L, -2, "env");
902
903         // Store environment as light userdata in registry
904         lua_pushlightuserdata(L, env);
905         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_env");
906
907         /*
908                 Add ActiveBlockModifiers to environment
909         */
910
911         // Get minetest.registered_abms
912         lua_getglobal(L, "minetest");
913         lua_getfield(L, -1, "registered_abms");
914         luaL_checktype(L, -1, LUA_TTABLE);
915         int registered_abms = lua_gettop(L);
916
917         if(lua_istable(L, registered_abms)){
918                 int table = lua_gettop(L);
919                 lua_pushnil(L);
920                 while(lua_next(L, table) != 0){
921                         // key at index -2 and value at index -1
922                         int id = lua_tonumber(L, -2);
923                         int current_abm = lua_gettop(L);
924
925                         std::set<std::string> trigger_contents;
926                         lua_getfield(L, current_abm, "nodenames");
927                         if(lua_istable(L, -1)){
928                                 int table = lua_gettop(L);
929                                 lua_pushnil(L);
930                                 while(lua_next(L, table) != 0){
931                                         // key at index -2 and value at index -1
932                                         luaL_checktype(L, -1, LUA_TSTRING);
933                                         trigger_contents.insert(lua_tostring(L, -1));
934                                         // removes value, keeps key for next iteration
935                                         lua_pop(L, 1);
936                                 }
937                         } else if(lua_isstring(L, -1)){
938                                 trigger_contents.insert(lua_tostring(L, -1));
939                         }
940                         lua_pop(L, 1);
941
942                         std::set<std::string> required_neighbors;
943                         lua_getfield(L, current_abm, "neighbors");
944                         if(lua_istable(L, -1)){
945                                 int table = lua_gettop(L);
946                                 lua_pushnil(L);
947                                 while(lua_next(L, table) != 0){
948                                         // key at index -2 and value at index -1
949                                         luaL_checktype(L, -1, LUA_TSTRING);
950                                         required_neighbors.insert(lua_tostring(L, -1));
951                                         // removes value, keeps key for next iteration
952                                         lua_pop(L, 1);
953                                 }
954                         } else if(lua_isstring(L, -1)){
955                                 required_neighbors.insert(lua_tostring(L, -1));
956                         }
957                         lua_pop(L, 1);
958
959                         float trigger_interval = 10.0;
960                         getfloatfield(L, current_abm, "interval", trigger_interval);
961
962                         int trigger_chance = 50;
963                         getintfield(L, current_abm, "chance", trigger_chance);
964
965                         LuaABM *abm = new LuaABM(L, id, trigger_contents,
966                                         required_neighbors, trigger_interval, trigger_chance);
967
968                         env->addActiveBlockModifier(abm);
969
970                         // removes value, keeps key for next iteration
971                         lua_pop(L, 1);
972                 }
973         }
974         lua_pop(L, 1);
975 }