]> git.lizzy.rs Git - dragonfireclient.git/blob - src/scriptapi_env.cpp
Pre-select current game in world creation dialog
[dragonfireclient.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         MapNode n = env->getMap().getNodeNoEx(pos);
231         try{
232                 MapNode n = env->getMap().getNode(pos);
233                 INodeDefManager *ndef = env->getGameDef()->ndef();
234                 lua_pushinteger(L, n.getLightBlend(dnr, ndef));
235                 return 1;
236         } catch(InvalidPositionException &e)
237         {
238                 lua_pushnil(L);
239                 return 1;
240         }
241 }
242
243 // EnvRef:place_node(pos, node)
244 // pos = {x=num, y=num, z=num}
245 int EnvRef::l_place_node(lua_State *L)
246 {
247         EnvRef *o = checkobject(L, 1);
248         ServerEnvironment *env = o->m_env;
249         if(env == NULL) return 0;
250         v3s16 pos = read_v3s16(L, 2);
251         MapNode n = readnode(L, 3, env->getGameDef()->ndef());
252
253         // Don't attempt to load non-loaded area as of now
254         MapNode n_old = env->getMap().getNodeNoEx(pos);
255         if(n_old.getContent() == CONTENT_IGNORE){
256                 lua_pushboolean(L, false);
257                 return 1;
258         }
259         // Create item to place
260         INodeDefManager *ndef = get_server(L)->ndef();
261         IItemDefManager *idef = get_server(L)->idef();
262         ItemStack item(ndef->get(n).name, 1, 0, "", idef);
263         // Make pointed position
264         PointedThing pointed;
265         pointed.type = POINTEDTHING_NODE;
266         pointed.node_abovesurface = pos;
267         pointed.node_undersurface = pos + v3s16(0,-1,0);
268         // Place it with a NULL placer (appears in Lua as a non-functional
269         // ObjectRef)
270         bool success = scriptapi_item_on_place(L, item, NULL, pointed);
271         lua_pushboolean(L, success);
272         return 1;
273 }
274
275 // EnvRef:dig_node(pos)
276 // pos = {x=num, y=num, z=num}
277 int EnvRef::l_dig_node(lua_State *L)
278 {
279         EnvRef *o = checkobject(L, 1);
280         ServerEnvironment *env = o->m_env;
281         if(env == NULL) return 0;
282         v3s16 pos = read_v3s16(L, 2);
283
284         // Don't attempt to load non-loaded area as of now
285         MapNode n = env->getMap().getNodeNoEx(pos);
286         if(n.getContent() == CONTENT_IGNORE){
287                 lua_pushboolean(L, false);
288                 return 1;
289         }
290         // Dig it out with a NULL digger (appears in Lua as a
291         // non-functional ObjectRef)
292         bool success = scriptapi_node_on_dig(L, pos, n, NULL);
293         lua_pushboolean(L, success);
294         return 1;
295 }
296
297 // EnvRef:punch_node(pos)
298 // pos = {x=num, y=num, z=num}
299 int EnvRef::l_punch_node(lua_State *L)
300 {
301         EnvRef *o = checkobject(L, 1);
302         ServerEnvironment *env = o->m_env;
303         if(env == NULL) return 0;
304         v3s16 pos = read_v3s16(L, 2);
305
306         // Don't attempt to load non-loaded area as of now
307         MapNode n = env->getMap().getNodeNoEx(pos);
308         if(n.getContent() == CONTENT_IGNORE){
309                 lua_pushboolean(L, false);
310                 return 1;
311         }
312         // Punch it with a NULL puncher (appears in Lua as a non-functional
313         // ObjectRef)
314         bool success = scriptapi_node_on_punch(L, pos, n, NULL);
315         lua_pushboolean(L, success);
316         return 1;
317 }
318
319 // EnvRef:get_meta(pos)
320 int EnvRef::l_get_meta(lua_State *L)
321 {
322         //infostream<<"EnvRef::l_get_meta()"<<std::endl;
323         EnvRef *o = checkobject(L, 1);
324         ServerEnvironment *env = o->m_env;
325         if(env == NULL) return 0;
326         // Do it
327         v3s16 p = read_v3s16(L, 2);
328         NodeMetaRef::create(L, p, env);
329         return 1;
330 }
331
332 // EnvRef:get_node_timer(pos)
333 int EnvRef::l_get_node_timer(lua_State *L)
334 {
335         EnvRef *o = checkobject(L, 1);
336         ServerEnvironment *env = o->m_env;
337         if(env == NULL) return 0;
338         // Do it
339         v3s16 p = read_v3s16(L, 2);
340         NodeTimerRef::create(L, p, env);
341         return 1;
342 }
343
344 // EnvRef:add_entity(pos, entityname) -> ObjectRef or nil
345 // pos = {x=num, y=num, z=num}
346 int EnvRef::l_add_entity(lua_State *L)
347 {
348         //infostream<<"EnvRef::l_add_entity()"<<std::endl;
349         EnvRef *o = checkobject(L, 1);
350         ServerEnvironment *env = o->m_env;
351         if(env == NULL) return 0;
352         // pos
353         v3f pos = checkFloatPos(L, 2);
354         // content
355         const char *name = luaL_checkstring(L, 3);
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         objectref_get_or_create(L, obj);
364         return 1;
365 }
366
367 // EnvRef:add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil
368 // pos = {x=num, y=num, z=num}
369 int EnvRef::l_add_item(lua_State *L)
370 {
371         //infostream<<"EnvRef::l_add_item()"<<std::endl;
372         EnvRef *o = checkobject(L, 1);
373         ServerEnvironment *env = o->m_env;
374         if(env == NULL) return 0;
375         // pos
376         v3f pos = checkFloatPos(L, 2);
377         // item
378         ItemStack item = read_item(L, 3);
379         if(item.empty() || !item.isKnown(get_server(L)->idef()))
380                 return 0;
381         // Use minetest.spawn_item to spawn a __builtin:item
382         lua_getglobal(L, "minetest");
383         lua_getfield(L, -1, "spawn_item");
384         if(lua_isnil(L, -1))
385                 return 0;
386         lua_pushvalue(L, 2);
387         lua_pushstring(L, item.getItemString().c_str());
388         if(lua_pcall(L, 2, 1, 0))
389                 script_error(L, "error: %s", lua_tostring(L, -1));
390         return 1;
391         /*lua_pushvalue(L, 1);
392         lua_pushstring(L, "__builtin:item");
393         lua_pushstring(L, item.getItemString().c_str());
394         return l_add_entity(L);*/
395         /*// Do it
396         ServerActiveObject *obj = createItemSAO(env, pos, item.getItemString());
397         int objectid = env->addActiveObject(obj);
398         // If failed to add, return nothing (reads as nil)
399         if(objectid == 0)
400                 return 0;
401         // Return ObjectRef
402         objectref_get_or_create(L, obj);
403         return 1;*/
404 }
405
406 // EnvRef:add_rat(pos)
407 // pos = {x=num, y=num, z=num}
408 int EnvRef::l_add_rat(lua_State *L)
409 {
410         infostream<<"EnvRef::l_add_rat(): C++ mobs have been removed."
411                         <<" Doing nothing."<<std::endl;
412         return 0;
413 }
414
415 // EnvRef:add_firefly(pos)
416 // pos = {x=num, y=num, z=num}
417 int EnvRef::l_add_firefly(lua_State *L)
418 {
419         infostream<<"EnvRef::l_add_firefly(): C++ mobs have been removed."
420                         <<" Doing nothing."<<std::endl;
421         return 0;
422 }
423
424 // EnvRef:get_player_by_name(name)
425 int EnvRef::l_get_player_by_name(lua_State *L)
426 {
427         EnvRef *o = checkobject(L, 1);
428         ServerEnvironment *env = o->m_env;
429         if(env == NULL) return 0;
430         // Do it
431         const char *name = luaL_checkstring(L, 2);
432         Player *player = env->getPlayer(name);
433         if(player == NULL){
434                 lua_pushnil(L);
435                 return 1;
436         }
437         PlayerSAO *sao = player->getPlayerSAO();
438         if(sao == NULL){
439                 lua_pushnil(L);
440                 return 1;
441         }
442         // Put player on stack
443         objectref_get_or_create(L, sao);
444         return 1;
445 }
446
447 // EnvRef:get_objects_inside_radius(pos, radius)
448 int EnvRef::l_get_objects_inside_radius(lua_State *L)
449 {
450         // Get the table insert function
451         lua_getglobal(L, "table");
452         lua_getfield(L, -1, "insert");
453         int table_insert = lua_gettop(L);
454         // Get environemnt
455         EnvRef *o = checkobject(L, 1);
456         ServerEnvironment *env = o->m_env;
457         if(env == NULL) return 0;
458         // Do it
459         v3f pos = checkFloatPos(L, 2);
460         float radius = luaL_checknumber(L, 3) * BS;
461         std::set<u16> ids = env->getObjectsInsideRadius(pos, radius);
462         lua_newtable(L);
463         int table = lua_gettop(L);
464         for(std::set<u16>::const_iterator
465                         i = ids.begin(); i != ids.end(); i++){
466                 ServerActiveObject *obj = env->getActiveObject(*i);
467                 // Insert object reference into table
468                 lua_pushvalue(L, table_insert);
469                 lua_pushvalue(L, table);
470                 objectref_get_or_create(L, obj);
471                 if(lua_pcall(L, 2, 0, 0))
472                         script_error(L, "error: %s", lua_tostring(L, -1));
473         }
474         return 1;
475 }
476
477 // EnvRef:set_timeofday(val)
478 // val = 0...1
479 int EnvRef::l_set_timeofday(lua_State *L)
480 {
481         EnvRef *o = checkobject(L, 1);
482         ServerEnvironment *env = o->m_env;
483         if(env == NULL) return 0;
484         // Do it
485         float timeofday_f = luaL_checknumber(L, 2);
486         assert(timeofday_f >= 0.0 && timeofday_f <= 1.0);
487         int timeofday_mh = (int)(timeofday_f * 24000.0);
488         // This should be set directly in the environment but currently
489         // such changes aren't immediately sent to the clients, so call
490         // the server instead.
491         //env->setTimeOfDay(timeofday_mh);
492         get_server(L)->setTimeOfDay(timeofday_mh);
493         return 0;
494 }
495
496 // EnvRef:get_timeofday() -> 0...1
497 int EnvRef::l_get_timeofday(lua_State *L)
498 {
499         EnvRef *o = checkobject(L, 1);
500         ServerEnvironment *env = o->m_env;
501         if(env == NULL) return 0;
502         // Do it
503         int timeofday_mh = env->getTimeOfDay();
504         float timeofday_f = (float)timeofday_mh / 24000.0;
505         lua_pushnumber(L, timeofday_f);
506         return 1;
507 }
508
509
510 // EnvRef:find_node_near(pos, radius, nodenames) -> pos or nil
511 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
512 int EnvRef::l_find_node_near(lua_State *L)
513 {
514         EnvRef *o = checkobject(L, 1);
515         ServerEnvironment *env = o->m_env;
516         if(env == NULL) return 0;
517         INodeDefManager *ndef = get_server(L)->ndef();
518         v3s16 pos = read_v3s16(L, 2);
519         int radius = luaL_checkinteger(L, 3);
520         std::set<content_t> filter;
521         if(lua_istable(L, 4)){
522                 int table = 4;
523                 lua_pushnil(L);
524                 while(lua_next(L, table) != 0){
525                         // key at index -2 and value at index -1
526                         luaL_checktype(L, -1, LUA_TSTRING);
527                         ndef->getIds(lua_tostring(L, -1), filter);
528                         // removes value, keeps key for next iteration
529                         lua_pop(L, 1);
530                 }
531         } else if(lua_isstring(L, 4)){
532                 ndef->getIds(lua_tostring(L, 4), filter);
533         }
534
535         for(int d=1; d<=radius; d++){
536                 std::list<v3s16> list;
537                 getFacePositions(list, d);
538                 for(std::list<v3s16>::iterator i = list.begin();
539                                 i != list.end(); ++i){
540                         v3s16 p = pos + (*i);
541                         content_t c = env->getMap().getNodeNoEx(p).getContent();
542                         if(filter.count(c) != 0){
543                                 push_v3s16(L, p);
544                                 return 1;
545                         }
546                 }
547         }
548         return 0;
549 }
550
551 // EnvRef:find_nodes_in_area(minp, maxp, nodenames) -> list of positions
552 // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
553 int EnvRef::l_find_nodes_in_area(lua_State *L)
554 {
555         EnvRef *o = checkobject(L, 1);
556         ServerEnvironment *env = o->m_env;
557         if(env == NULL) return 0;
558         INodeDefManager *ndef = get_server(L)->ndef();
559         v3s16 minp = read_v3s16(L, 2);
560         v3s16 maxp = read_v3s16(L, 3);
561         std::set<content_t> filter;
562         if(lua_istable(L, 4)){
563                 int table = 4;
564                 lua_pushnil(L);
565                 while(lua_next(L, table) != 0){
566                         // key at index -2 and value at index -1
567                         luaL_checktype(L, -1, LUA_TSTRING);
568                         ndef->getIds(lua_tostring(L, -1), filter);
569                         // removes value, keeps key for next iteration
570                         lua_pop(L, 1);
571                 }
572         } else if(lua_isstring(L, 4)){
573                 ndef->getIds(lua_tostring(L, 4), filter);
574         }
575
576         // Get the table insert function
577         lua_getglobal(L, "table");
578         lua_getfield(L, -1, "insert");
579         int table_insert = lua_gettop(L);
580
581         lua_newtable(L);
582         int table = lua_gettop(L);
583         for(s16 x=minp.X; x<=maxp.X; x++)
584         for(s16 y=minp.Y; y<=maxp.Y; y++)
585         for(s16 z=minp.Z; z<=maxp.Z; z++)
586         {
587                 v3s16 p(x,y,z);
588                 content_t c = env->getMap().getNodeNoEx(p).getContent();
589                 if(filter.count(c) != 0){
590                         lua_pushvalue(L, table_insert);
591                         lua_pushvalue(L, table);
592                         push_v3s16(L, p);
593                         if(lua_pcall(L, 2, 0, 0))
594                                 script_error(L, "error: %s", lua_tostring(L, -1));
595                 }
596         }
597         return 1;
598 }
599
600 //      EnvRef:get_perlin(seeddiff, octaves, persistence, scale)
601 //  returns world-specific PerlinNoise
602 int EnvRef::l_get_perlin(lua_State *L)
603 {
604         EnvRef *o = checkobject(L, 1);
605         ServerEnvironment *env = o->m_env;
606         if(env == NULL) return 0;
607
608         int seeddiff = luaL_checkint(L, 2);
609         int octaves = luaL_checkint(L, 3);
610         float persistence = luaL_checknumber(L, 4);
611         float scale = luaL_checknumber(L, 5);
612
613         LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale);
614         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
615         luaL_getmetatable(L, "PerlinNoise");
616         lua_setmetatable(L, -2);
617         return 1;
618 }
619
620 //  EnvRef:get_perlin_map(noiseparams, size)
621 //  returns world-specific PerlinNoiseMap
622 int EnvRef::l_get_perlin_map(lua_State *L)
623 {
624         EnvRef *o = checkobject(L, 1);
625         ServerEnvironment *env = o->m_env;
626         if (env == NULL)
627                 return 0;
628
629         NoiseParams *np = read_noiseparams(L, 2);
630         if (!np)
631                 return 0;
632         v3s16 size = read_v3s16(L, 3);
633
634         int seed = (int)(env->getServerMap().getSeed());
635         LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(np, seed, size);
636         *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
637         luaL_getmetatable(L, "PerlinNoiseMap");
638         lua_setmetatable(L, -2);
639         return 1;
640 }
641
642 // EnvRef:clear_objects()
643 // clear all objects in the environment
644 int EnvRef::l_clear_objects(lua_State *L)
645 {
646         EnvRef *o = checkobject(L, 1);
647         o->m_env->clearAllObjects();
648         return 0;
649 }
650
651 int EnvRef::l_line_of_sight(lua_State *L) {
652         float stepsize = 1.0;
653
654         //infostream<<"EnvRef::l_get_node()"<<std::endl;
655         EnvRef *o = checkobject(L, 1);
656         ServerEnvironment *env = o->m_env;
657         if(env == NULL) return 0;
658
659         // read position 1 from lua
660         v3f pos1 = checkFloatPos(L, 2);
661         // read position 2 from lua
662         v3f pos2 = checkFloatPos(L, 2);
663         //read step size from lua
664         if(lua_isnumber(L, 3))
665                 stepsize = lua_tonumber(L, 3);
666
667         lua_pushboolean(L, env->line_of_sight(pos1,pos2,stepsize));
668
669         return 1;
670 }
671
672 int EnvRef::l_find_path(lua_State *L)
673 {
674         EnvRef *o = checkobject(L, 1);
675         ServerEnvironment *env = o->m_env;
676
677         if(env == NULL) return 0;
678
679         v3s16 pos1                  = read_v3s16(L, 2);
680         v3s16 pos2                  = read_v3s16(L, 3);
681         unsigned int searchdistance = luaL_checkint(L, 4);
682         unsigned int max_jump       = luaL_checkint(L, 5);
683         unsigned int max_drop       = luaL_checkint(L, 6);
684         algorithm algo              = A_PLAIN_NP;
685         if(! lua_isnil(L, 7)) {
686                 std::string algorithm       = luaL_checkstring(L,7);
687
688                 if (algorithm == "A*")
689                         algo = A_PLAIN;
690
691                 if (algorithm == "Dijkstra")
692                         algo = DIJKSTRA;
693         }
694
695         std::vector<v3s16> path =
696                         get_Path(env,pos1,pos2,searchdistance,max_jump,max_drop,algo);
697
698         if (path.size() > 0)
699         {
700                 lua_newtable(L);
701                 int top = lua_gettop(L);
702                 unsigned int index = 1;
703                 for (std::vector<v3s16>::iterator i = path.begin(); i != path.end();i++)
704                 {
705                         lua_pushnumber(L,index);
706                         push_v3s16(L, *i);
707                         lua_settable(L, top);
708                         index++;
709                 }
710                 return 1;
711         }
712
713         return 0;
714 }
715
716 int EnvRef::l_spawn_tree(lua_State *L)
717 {
718         EnvRef *o = checkobject(L, 1);
719         ServerEnvironment *env = o->m_env;
720         if(env == NULL) return 0;
721         v3s16 p0 = read_v3s16(L, 2);
722
723         treegen::TreeDef tree_def;
724         std::string trunk,leaves,fruit;
725         INodeDefManager *ndef = env->getGameDef()->ndef();
726
727         if(lua_istable(L, 3))
728         {
729                 getstringfield(L, 3, "axiom", tree_def.initial_axiom);
730                 getstringfield(L, 3, "rules_a", tree_def.rules_a);
731                 getstringfield(L, 3, "rules_b", tree_def.rules_b);
732                 getstringfield(L, 3, "rules_c", tree_def.rules_c);
733                 getstringfield(L, 3, "rules_d", tree_def.rules_d);
734                 getstringfield(L, 3, "trunk", trunk);
735                 tree_def.trunknode=ndef->getId(trunk);
736                 getstringfield(L, 3, "leaves", leaves);
737                 tree_def.leavesnode=ndef->getId(leaves);
738                 tree_def.leaves2_chance=0;
739                 getstringfield(L, 3, "leaves2", leaves);
740                 if (leaves !="")
741                 {
742                         tree_def.leaves2node=ndef->getId(leaves);
743                         getintfield(L, 3, "leaves2_chance", tree_def.leaves2_chance);
744                 }
745                 getintfield(L, 3, "angle", tree_def.angle);
746                 getintfield(L, 3, "iterations", tree_def.iterations);
747                 getintfield(L, 3, "random_level", tree_def.iterations_random_level);
748                 getstringfield(L, 3, "trunk_type", tree_def.trunk_type);
749                 getboolfield(L, 3, "thin_branches", tree_def.thin_branches);
750                 tree_def.fruit_chance=0;
751                 getstringfield(L, 3, "fruit", fruit);
752                 if (fruit != "")
753                 {
754                         tree_def.fruitnode=ndef->getId(fruit);
755                         getintfield(L, 3, "fruit_chance",tree_def.fruit_chance);
756                 }
757                 getintfield(L, 3, "seed", tree_def.seed);
758         }
759         else
760                 return 0;
761         treegen::spawn_ltree (env, p0, ndef, tree_def);
762         return 1;
763 }
764
765
766 EnvRef::EnvRef(ServerEnvironment *env):
767         m_env(env)
768 {
769         //infostream<<"EnvRef created"<<std::endl;
770 }
771
772 EnvRef::~EnvRef()
773 {
774         //infostream<<"EnvRef destructing"<<std::endl;
775 }
776
777 // Creates an EnvRef and leaves it on top of stack
778 // Not callable from Lua; all references are created on the C side.
779 void EnvRef::create(lua_State *L, ServerEnvironment *env)
780 {
781         EnvRef *o = new EnvRef(env);
782         //infostream<<"EnvRef::create: o="<<o<<std::endl;
783         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
784         luaL_getmetatable(L, className);
785         lua_setmetatable(L, -2);
786 }
787
788 void EnvRef::set_null(lua_State *L)
789 {
790         EnvRef *o = checkobject(L, -1);
791         o->m_env = NULL;
792 }
793
794 void EnvRef::Register(lua_State *L)
795 {
796         lua_newtable(L);
797         int methodtable = lua_gettop(L);
798         luaL_newmetatable(L, className);
799         int metatable = lua_gettop(L);
800
801         lua_pushliteral(L, "__metatable");
802         lua_pushvalue(L, methodtable);
803         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
804
805         lua_pushliteral(L, "__index");
806         lua_pushvalue(L, methodtable);
807         lua_settable(L, metatable);
808
809         lua_pushliteral(L, "__gc");
810         lua_pushcfunction(L, gc_object);
811         lua_settable(L, metatable);
812
813         lua_pop(L, 1);  // drop metatable
814
815         luaL_openlib(L, 0, methods, 0);  // fill methodtable
816         lua_pop(L, 1);  // drop methodtable
817
818         // Cannot be created from Lua
819         //lua_register(L, className, create_object);
820 }
821
822 const char EnvRef::className[] = "EnvRef";
823 const luaL_reg EnvRef::methods[] = {
824         luamethod(EnvRef, set_node),
825         luamethod(EnvRef, add_node),
826         luamethod(EnvRef, remove_node),
827         luamethod(EnvRef, get_node),
828         luamethod(EnvRef, get_node_or_nil),
829         luamethod(EnvRef, get_node_light),
830         luamethod(EnvRef, place_node),
831         luamethod(EnvRef, dig_node),
832         luamethod(EnvRef, punch_node),
833         luamethod(EnvRef, add_entity),
834         luamethod(EnvRef, add_item),
835         luamethod(EnvRef, add_rat),
836         luamethod(EnvRef, add_firefly),
837         luamethod(EnvRef, get_meta),
838         luamethod(EnvRef, get_node_timer),
839         luamethod(EnvRef, get_player_by_name),
840         luamethod(EnvRef, get_objects_inside_radius),
841         luamethod(EnvRef, set_timeofday),
842         luamethod(EnvRef, get_timeofday),
843         luamethod(EnvRef, find_node_near),
844         luamethod(EnvRef, find_nodes_in_area),
845         luamethod(EnvRef, get_perlin),
846         luamethod(EnvRef, get_perlin_map),
847         luamethod(EnvRef, clear_objects),
848         luamethod(EnvRef, spawn_tree),
849         luamethod(EnvRef, line_of_sight),
850         luamethod(EnvRef, find_path),
851         {0,0}
852 };
853
854 void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp,
855                 u32 blockseed)
856 {
857         realitycheck(L);
858         assert(lua_checkstack(L, 20));
859         //infostream<<"scriptapi_environment_on_generated"<<std::endl;
860         StackUnroller stack_unroller(L);
861
862         // Get minetest.registered_on_generateds
863         lua_getglobal(L, "minetest");
864         lua_getfield(L, -1, "registered_on_generateds");
865         // Call callbacks
866         push_v3s16(L, minp);
867         push_v3s16(L, maxp);
868         lua_pushnumber(L, blockseed);
869         scriptapi_run_callbacks(L, 3, RUN_CALLBACKS_MODE_FIRST);
870 }
871
872 void scriptapi_environment_step(lua_State *L, float dtime)
873 {
874         realitycheck(L);
875         assert(lua_checkstack(L, 20));
876         //infostream<<"scriptapi_environment_step"<<std::endl;
877         StackUnroller stack_unroller(L);
878
879         // Get minetest.registered_globalsteps
880         lua_getglobal(L, "minetest");
881         lua_getfield(L, -1, "registered_globalsteps");
882         // Call callbacks
883         lua_pushnumber(L, dtime);
884         scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
885 }
886
887 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
888 {
889         realitycheck(L);
890         assert(lua_checkstack(L, 20));
891         verbosestream<<"scriptapi_add_environment"<<std::endl;
892         StackUnroller stack_unroller(L);
893
894         // Create EnvRef on stack
895         EnvRef::create(L, env);
896         int envref = lua_gettop(L);
897
898         // minetest.env = envref
899         lua_getglobal(L, "minetest");
900         luaL_checktype(L, -1, LUA_TTABLE);
901         lua_pushvalue(L, envref);
902         lua_setfield(L, -2, "env");
903
904         // Store environment as light userdata in registry
905         lua_pushlightuserdata(L, env);
906         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_env");
907
908         /*
909                 Add ActiveBlockModifiers to environment
910         */
911
912         // Get minetest.registered_abms
913         lua_getglobal(L, "minetest");
914         lua_getfield(L, -1, "registered_abms");
915         luaL_checktype(L, -1, LUA_TTABLE);
916         int registered_abms = lua_gettop(L);
917
918         if(lua_istable(L, registered_abms)){
919                 int table = lua_gettop(L);
920                 lua_pushnil(L);
921                 while(lua_next(L, table) != 0){
922                         // key at index -2 and value at index -1
923                         int id = lua_tonumber(L, -2);
924                         int current_abm = lua_gettop(L);
925
926                         std::set<std::string> trigger_contents;
927                         lua_getfield(L, current_abm, "nodenames");
928                         if(lua_istable(L, -1)){
929                                 int table = lua_gettop(L);
930                                 lua_pushnil(L);
931                                 while(lua_next(L, table) != 0){
932                                         // key at index -2 and value at index -1
933                                         luaL_checktype(L, -1, LUA_TSTRING);
934                                         trigger_contents.insert(lua_tostring(L, -1));
935                                         // removes value, keeps key for next iteration
936                                         lua_pop(L, 1);
937                                 }
938                         } else if(lua_isstring(L, -1)){
939                                 trigger_contents.insert(lua_tostring(L, -1));
940                         }
941                         lua_pop(L, 1);
942
943                         std::set<std::string> required_neighbors;
944                         lua_getfield(L, current_abm, "neighbors");
945                         if(lua_istable(L, -1)){
946                                 int table = lua_gettop(L);
947                                 lua_pushnil(L);
948                                 while(lua_next(L, table) != 0){
949                                         // key at index -2 and value at index -1
950                                         luaL_checktype(L, -1, LUA_TSTRING);
951                                         required_neighbors.insert(lua_tostring(L, -1));
952                                         // removes value, keeps key for next iteration
953                                         lua_pop(L, 1);
954                                 }
955                         } else if(lua_isstring(L, -1)){
956                                 required_neighbors.insert(lua_tostring(L, -1));
957                         }
958                         lua_pop(L, 1);
959
960                         float trigger_interval = 10.0;
961                         getfloatfield(L, current_abm, "interval", trigger_interval);
962
963                         int trigger_chance = 50;
964                         getintfield(L, current_abm, "chance", trigger_chance);
965
966                         LuaABM *abm = new LuaABM(L, id, trigger_contents,
967                                         required_neighbors, trigger_interval, trigger_chance);
968
969                         env->addActiveBlockModifier(abm);
970
971                         // removes value, keeps key for next iteration
972                         lua_pop(L, 1);
973                 }
974         }
975         lua_pop(L, 1);
976 }