]> git.lizzy.rs Git - minetest.git/blob - src/scriptapi.cpp
Tune main menu a bit and show version number in there
[minetest.git] / src / scriptapi.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2011 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 General Public License as published by
7 the Free Software Foundation; either version 2 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 General Public License for more details.
14
15 You should have received a copy of the GNU 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
22 #include <iostream>
23 #include <list>
24 extern "C" {
25 #include <lua.h>
26 #include <lualib.h>
27 #include <lauxlib.h>
28 }
29
30 #include "log.h"
31 #include "server.h"
32 #include "porting.h"
33 #include "filesys.h"
34 #include "serverobject.h"
35 #include "script.h"
36 //#include "luna.h"
37 #include "luaentity_common.h"
38 #include "content_sao.h" // For LuaEntitySAO
39 #include "tooldef.h"
40 #include "nodedef.h"
41 #include "craftdef.h"
42 #include "craftitemdef.h"
43 #include "main.h" // For g_settings
44 #include "settings.h" // For accessing g_settings
45 #include "nodemetadata.h"
46 #include "mapblock.h" // For getNodeBlockPos
47 #include "content_nodemeta.h"
48 #include "utility.h"
49
50 static void stackDump(lua_State *L, std::ostream &o)
51 {
52   int i;
53   int top = lua_gettop(L);
54   for (i = 1; i <= top; i++) {  /* repeat for each level */
55         int t = lua_type(L, i);
56         switch (t) {
57
58           case LUA_TSTRING:  /* strings */
59                 o<<"\""<<lua_tostring(L, i)<<"\"";
60                 break;
61
62           case LUA_TBOOLEAN:  /* booleans */
63                 o<<(lua_toboolean(L, i) ? "true" : "false");
64                 break;
65
66           case LUA_TNUMBER:  /* numbers */ {
67                 char buf[10];
68                 snprintf(buf, 10, "%g", lua_tonumber(L, i));
69                 o<<buf;
70                 break; }
71
72           default:  /* other values */
73                 o<<lua_typename(L, t);
74                 break;
75
76         }
77         o<<" ";
78   }
79   o<<std::endl;
80 }
81
82 static void realitycheck(lua_State *L)
83 {
84         int top = lua_gettop(L);
85         if(top >= 30){
86                 dstream<<"Stack is over 30:"<<std::endl;
87                 stackDump(L, dstream);
88                 script_error(L, "Stack is over 30 (reality check)");
89         }
90 }
91
92 class StackUnroller
93 {
94 private:
95         lua_State *m_lua;
96         int m_original_top;
97 public:
98         StackUnroller(lua_State *L):
99                 m_lua(L),
100                 m_original_top(-1)
101         {
102                 m_original_top = lua_gettop(m_lua); // store stack height
103         }
104         ~StackUnroller()
105         {
106                 lua_settop(m_lua, m_original_top); // restore stack height
107         }
108 };
109
110 static v3f readFloatPos(lua_State *L, int index)
111 {
112         v3f pos;
113         luaL_checktype(L, index, LUA_TTABLE);
114         lua_getfield(L, index, "x");
115         pos.X = lua_tonumber(L, -1);
116         lua_pop(L, 1);
117         lua_getfield(L, index, "y");
118         pos.Y = lua_tonumber(L, -1);
119         lua_pop(L, 1);
120         lua_getfield(L, index, "z");
121         pos.Z = lua_tonumber(L, -1);
122         lua_pop(L, 1);
123         pos *= BS; // Scale to internal format
124         return pos;
125 }
126
127 static void pushFloatPos(lua_State *L, v3f p)
128 {
129         p /= BS;
130         lua_newtable(L);
131         lua_pushnumber(L, p.X);
132         lua_setfield(L, -2, "x");
133         lua_pushnumber(L, p.Y);
134         lua_setfield(L, -2, "y");
135         lua_pushnumber(L, p.Z);
136         lua_setfield(L, -2, "z");
137 }
138
139 static void pushpos(lua_State *L, v3s16 p)
140 {
141         lua_newtable(L);
142         lua_pushnumber(L, p.X);
143         lua_setfield(L, -2, "x");
144         lua_pushnumber(L, p.Y);
145         lua_setfield(L, -2, "y");
146         lua_pushnumber(L, p.Z);
147         lua_setfield(L, -2, "z");
148 }
149
150 static v3s16 readpos(lua_State *L, int index)
151 {
152         // Correct rounding at <0
153         v3f pf = readFloatPos(L, index);
154         return floatToInt(pf, BS);
155 }
156
157 static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
158 {
159         lua_newtable(L);
160         lua_pushstring(L, ndef->get(n).name.c_str());
161         lua_setfield(L, -2, "name");
162         lua_pushnumber(L, n.getParam1());
163         lua_setfield(L, -2, "param1");
164         lua_pushnumber(L, n.getParam2());
165         lua_setfield(L, -2, "param2");
166 }
167
168 static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
169 {
170         lua_getfield(L, index, "name");
171         const char *name = lua_tostring(L, -1);
172         lua_pop(L, 1);
173         u8 param1;
174         lua_getfield(L, index, "param1");
175         if(lua_isnil(L, -1))
176                 param1 = 0;
177         else
178                 param1 = lua_tonumber(L, -1);
179         lua_pop(L, 1);
180         u8 param2;
181         lua_getfield(L, index, "param2");
182         if(lua_isnil(L, -1))
183                 param2 = 0;
184         else
185                 param2 = lua_tonumber(L, -1);
186         lua_pop(L, 1);
187         return MapNode(ndef, name, param1, param2);
188 }
189
190 static video::SColor readARGB8(lua_State *L, int index)
191 {
192         video::SColor color;
193         luaL_checktype(L, index, LUA_TTABLE);
194         lua_getfield(L, index, "a");
195         if(lua_isnumber(L, -1))
196                 color.setAlpha(lua_tonumber(L, -1));
197         lua_pop(L, 1);
198         lua_getfield(L, index, "r");
199         color.setRed(lua_tonumber(L, -1));
200         lua_pop(L, 1);
201         lua_getfield(L, index, "g");
202         color.setGreen(lua_tonumber(L, -1));
203         lua_pop(L, 1);
204         lua_getfield(L, index, "b");
205         color.setBlue(lua_tonumber(L, -1));
206         lua_pop(L, 1);
207         return color;
208 }
209
210 static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
211 {
212         core::aabbox3d<f32> box;
213         if(lua_istable(L, -1)){
214                 lua_rawgeti(L, -1, 1);
215                 box.MinEdge.X = lua_tonumber(L, -1) * scale;
216                 lua_pop(L, 1);
217                 lua_rawgeti(L, -1, 2);
218                 box.MinEdge.Y = lua_tonumber(L, -1) * scale;
219                 lua_pop(L, 1);
220                 lua_rawgeti(L, -1, 3);
221                 box.MinEdge.Z = lua_tonumber(L, -1) * scale;
222                 lua_pop(L, 1);
223                 lua_rawgeti(L, -1, 4);
224                 box.MaxEdge.X = lua_tonumber(L, -1) * scale;
225                 lua_pop(L, 1);
226                 lua_rawgeti(L, -1, 5);
227                 box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
228                 lua_pop(L, 1);
229                 lua_rawgeti(L, -1, 6);
230                 box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
231                 lua_pop(L, 1);
232         }
233         return box;
234 }
235
236 static v2s16 read_v2s16(lua_State *L, int index)
237 {
238         v2s16 p;
239         luaL_checktype(L, index, LUA_TTABLE);
240         lua_getfield(L, index, "x");
241         p.X = lua_tonumber(L, -1);
242         lua_pop(L, 1);
243         lua_getfield(L, index, "y");
244         p.Y = lua_tonumber(L, -1);
245         lua_pop(L, 1);
246         return p;
247 }
248
249 static v2f read_v2f(lua_State *L, int index)
250 {
251         v2f p;
252         luaL_checktype(L, index, LUA_TTABLE);
253         lua_getfield(L, index, "x");
254         p.X = lua_tonumber(L, -1);
255         lua_pop(L, 1);
256         lua_getfield(L, index, "y");
257         p.Y = lua_tonumber(L, -1);
258         lua_pop(L, 1);
259         return p;
260 }
261
262 static bool getstringfield(lua_State *L, int table,
263                 const char *fieldname, std::string &result)
264 {
265         lua_getfield(L, table, fieldname);
266         bool got = false;
267         if(lua_isstring(L, -1)){
268                 result = lua_tostring(L, -1);
269                 got = true;
270         }
271         lua_pop(L, 1);
272         return got;
273 }
274
275 static bool getintfield(lua_State *L, int table,
276                 const char *fieldname, int &result)
277 {
278         lua_getfield(L, table, fieldname);
279         bool got = false;
280         if(lua_isnumber(L, -1)){
281                 result = lua_tonumber(L, -1);
282                 got = true;
283         }
284         lua_pop(L, 1);
285         return got;
286 }
287
288 static bool getfloatfield(lua_State *L, int table,
289                 const char *fieldname, float &result)
290 {
291         lua_getfield(L, table, fieldname);
292         bool got = false;
293         if(lua_isnumber(L, -1)){
294                 result = lua_tonumber(L, -1);
295                 got = true;
296         }
297         lua_pop(L, 1);
298         return got;
299 }
300
301 static bool getboolfield(lua_State *L, int table,
302                 const char *fieldname, bool &result)
303 {
304         lua_getfield(L, table, fieldname);
305         bool got = false;
306         if(lua_isboolean(L, -1)){
307                 result = lua_toboolean(L, -1);
308                 got = true;
309         }
310         lua_pop(L, 1);
311         return got;
312 }
313
314 static std::string getstringfield_default(lua_State *L, int table,
315                 const char *fieldname, const std::string &default_)
316 {
317         std::string result = default_;
318         getstringfield(L, table, fieldname, result);
319         return result;
320 }
321
322 static int getintfield_default(lua_State *L, int table,
323                 const char *fieldname, int default_)
324 {
325         int result = default_;
326         getintfield(L, table, fieldname, result);
327         return result;
328 }
329
330 /*static float getfloatfield_default(lua_State *L, int table,
331                 const char *fieldname, float default_)
332 {
333         float result = default_;
334         getfloatfield(L, table, fieldname, result);
335         return result;
336 }*/
337
338 static bool getboolfield_default(lua_State *L, int table,
339                 const char *fieldname, bool default_)
340 {
341         bool result = default_;
342         getboolfield(L, table, fieldname, result);
343         return result;
344 }
345
346 struct EnumString
347 {
348         int num;
349         const char *str;
350 };
351
352 static bool string_to_enum(const EnumString *spec, int &result,
353                 const std::string &str)
354 {
355         const EnumString *esp = spec;
356         while(esp->str){
357                 if(str == std::string(esp->str)){
358                         result = esp->num;
359                         return true;
360                 }
361                 esp++;
362         }
363         return false;
364 }
365
366 /*static bool enum_to_string(const EnumString *spec, std::string &result,
367                 int num)
368 {
369         const EnumString *esp = spec;
370         while(esp){
371                 if(num == esp->num){
372                         result = esp->str;
373                         return true;
374                 }
375                 esp++;
376         }
377         return false;
378 }*/
379
380 static int getenumfield(lua_State *L, int table,
381                 const char *fieldname, const EnumString *spec, int default_)
382 {
383         int result = default_;
384         string_to_enum(spec, result,
385                         getstringfield_default(L, table, fieldname, ""));
386         return result;
387 }
388
389 struct EnumString es_DrawType[] =
390 {
391         {NDT_NORMAL, "normal"},
392         {NDT_AIRLIKE, "airlike"},
393         {NDT_LIQUID, "liquid"},
394         {NDT_FLOWINGLIQUID, "flowingliquid"},
395         {NDT_GLASSLIKE, "glasslike"},
396         {NDT_ALLFACES, "allfaces"},
397         {NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
398         {NDT_TORCHLIKE, "torchlike"},
399         {NDT_SIGNLIKE, "signlike"},
400         {NDT_PLANTLIKE, "plantlike"},
401         {NDT_FENCELIKE, "fencelike"},
402         {NDT_RAILLIKE, "raillike"},
403         {0, NULL},
404 };
405
406 struct EnumString es_ContentParamType[] =
407 {
408         {CPT_NONE, "none"},
409         {CPT_LIGHT, "light"},
410         {CPT_MINERAL, "mineral"},
411         {CPT_FACEDIR_SIMPLE, "facedir_simple"},
412         {0, NULL},
413 };
414
415 struct EnumString es_LiquidType[] =
416 {
417         {LIQUID_NONE, "none"},
418         {LIQUID_FLOWING, "flowing"},
419         {LIQUID_SOURCE, "source"},
420         {0, NULL},
421 };
422
423 struct EnumString es_NodeBoxType[] =
424 {
425         {NODEBOX_REGULAR, "regular"},
426         {NODEBOX_FIXED, "fixed"},
427         {NODEBOX_WALLMOUNTED, "wallmounted"},
428         {0, NULL},
429 };
430
431 struct EnumString es_Diggability[] =
432 {
433         {DIGGABLE_NOT, "not"},
434         {DIGGABLE_NORMAL, "normal"},
435         {DIGGABLE_CONSTANT, "constant"},
436         {0, NULL},
437 };
438
439 /*
440         Global functions
441 */
442
443 static int l_register_nodedef_defaults(lua_State *L)
444 {
445         luaL_checktype(L, 1, LUA_TTABLE);
446
447         lua_pushvalue(L, 1); // Explicitly put parameter 1 on top of stack
448         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
449
450         return 0;
451 }
452
453 // Register new object prototype
454 // register_entity(name, prototype)
455 static int l_register_entity(lua_State *L)
456 {
457         const char *name = luaL_checkstring(L, 1);
458         infostream<<"register_entity: "<<name<<std::endl;
459         luaL_checktype(L, 2, LUA_TTABLE);
460
461         // Get minetest.registered_entities
462         lua_getglobal(L, "minetest");
463         lua_getfield(L, -1, "registered_entities");
464         luaL_checktype(L, -1, LUA_TTABLE);
465         int registered_entities = lua_gettop(L);
466         lua_pushvalue(L, 2); // Object = param 2 -> stack top
467         // registered_entities[name] = object
468         lua_setfield(L, registered_entities, name);
469         
470         // Get registered object to top of stack
471         lua_pushvalue(L, 2);
472         
473         // Set __index to point to itself
474         lua_pushvalue(L, -1);
475         lua_setfield(L, -2, "__index");
476
477         // Set metatable.__index = metatable
478         luaL_getmetatable(L, "minetest.entity");
479         lua_pushvalue(L, -1); // duplicate metatable
480         lua_setfield(L, -2, "__index");
481         // Set object metatable
482         lua_setmetatable(L, -2);
483
484         return 0; /* number of results */
485 }
486
487 class LuaABM : public ActiveBlockModifier
488 {
489 private:
490         lua_State *m_lua;
491         int m_id;
492
493         std::set<std::string> m_trigger_contents;
494         float m_trigger_interval;
495         u32 m_trigger_chance;
496 public:
497         LuaABM(lua_State *L, int id,
498                         const std::set<std::string> &trigger_contents,
499                         float trigger_interval, u32 trigger_chance):
500                 m_lua(L),
501                 m_id(id),
502                 m_trigger_contents(trigger_contents),
503                 m_trigger_interval(trigger_interval),
504                 m_trigger_chance(trigger_chance)
505         {
506         }
507         virtual std::set<std::string> getTriggerContents()
508         {
509                 return m_trigger_contents;
510         }
511         virtual float getTriggerInterval()
512         {
513                 return m_trigger_interval;
514         }
515         virtual u32 getTriggerChance()
516         {
517                 return m_trigger_chance;
518         }
519         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
520                         u32 active_object_count, u32 active_object_count_wider)
521         {
522                 lua_State *L = m_lua;
523         
524                 realitycheck(L);
525                 assert(lua_checkstack(L, 20));
526                 StackUnroller stack_unroller(L);
527
528                 // Get minetest.registered_abms
529                 lua_getglobal(L, "minetest");
530                 lua_getfield(L, -1, "registered_abms");
531                 luaL_checktype(L, -1, LUA_TTABLE);
532                 int registered_abms = lua_gettop(L);
533
534                 // Get minetest.registered_abms[m_id]
535                 lua_pushnumber(L, m_id);
536                 lua_gettable(L, registered_abms);
537                 if(lua_isnil(L, -1))
538                         assert(0);
539                 
540                 // Call action
541                 luaL_checktype(L, -1, LUA_TTABLE);
542                 lua_getfield(L, -1, "action");
543                 luaL_checktype(L, -1, LUA_TFUNCTION);
544                 pushpos(L, p);
545                 pushnode(L, n, env->getGameDef()->ndef());
546                 lua_pushnumber(L, active_object_count);
547                 lua_pushnumber(L, active_object_count_wider);
548                 if(lua_pcall(L, 4, 0, 0))
549                         script_error(L, "error: %s\n", lua_tostring(L, -1));
550         }
551 };
552
553 // register_abm({...})
554 static int l_register_abm(lua_State *L)
555 {
556         infostream<<"register_abm"<<std::endl;
557         luaL_checktype(L, 1, LUA_TTABLE);
558
559         // Get minetest.registered_abms
560         lua_getglobal(L, "minetest");
561         lua_getfield(L, -1, "registered_abms");
562         luaL_checktype(L, -1, LUA_TTABLE);
563         int registered_abms = lua_gettop(L);
564
565         int id = 1;
566         // Find free id
567         for(;;){
568                 lua_pushnumber(L, id);
569                 lua_gettable(L, registered_abms);
570                 if(lua_isnil(L, -1))
571                         break;
572                 lua_pop(L, 1);
573                 id++;
574         }
575         lua_pop(L, 1);
576
577         infostream<<"register_abm: id="<<id<<std::endl;
578
579         // registered_abms[id] = spec
580         lua_pushnumber(L, id);
581         lua_pushvalue(L, 1);
582         lua_settable(L, registered_abms);
583         
584         return 0; /* number of results */
585 }
586
587 // register_tool(name, {lots of stuff})
588 static int l_register_tool(lua_State *L)
589 {
590         const char *name = luaL_checkstring(L, 1);
591         infostream<<"register_tool: "<<name<<std::endl;
592         luaL_checktype(L, 2, LUA_TTABLE);
593         int table = 2;
594
595         // Get server from registry
596         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
597         Server *server = (Server*)lua_touserdata(L, -1);
598         // And get the writable tool definition manager from the server
599         IWritableToolDefManager *tooldef =
600                         server->getWritableToolDefManager();
601         
602         ToolDefinition def;
603         
604         getstringfield(L, table, "image", def.imagename);
605         getfloatfield(L, table, "basetime", def.properties.basetime);
606         getfloatfield(L, table, "dt_weight", def.properties.dt_weight);
607         getfloatfield(L, table, "dt_crackiness", def.properties.dt_crackiness);
608         getfloatfield(L, table, "dt_crumbliness", def.properties.dt_crumbliness);
609         getfloatfield(L, table, "dt_cuttability", def.properties.dt_cuttability);
610         getfloatfield(L, table, "basedurability", def.properties.basedurability);
611         getfloatfield(L, table, "dd_weight", def.properties.dd_weight);
612         getfloatfield(L, table, "dd_crackiness", def.properties.dd_crackiness);
613         getfloatfield(L, table, "dd_crumbliness", def.properties.dd_crumbliness);
614         getfloatfield(L, table, "dd_cuttability", def.properties.dd_cuttability);
615
616         tooldef->registerTool(name, def);
617         return 0; /* number of results */
618 }
619
620 // register_craftitem(name, {lots of stuff})
621 static int l_register_craftitem(lua_State *L)
622 {
623         const char *name = luaL_checkstring(L, 1);
624         infostream<<"register_craftitem: "<<name<<std::endl;
625         luaL_checktype(L, 2, LUA_TTABLE);
626         int table = 2;
627
628         // Get server from registry
629         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
630         Server *server = (Server*)lua_touserdata(L, -1);
631         // And get the writable CraftItem definition manager from the server
632         IWritableCraftItemDefManager *craftitemdef =
633                         server->getWritableCraftItemDefManager();
634         
635         // Check if on_drop is defined
636         lua_getfield(L, table, "on_drop");
637         bool got_on_drop = !lua_isnil(L, -1);
638         lua_pop(L, 1);
639
640         // Check if on_use is defined
641         lua_getfield(L, table, "on_use");
642         bool got_on_use = !lua_isnil(L, -1);
643         lua_pop(L, 1);
644
645         CraftItemDefinition def;
646         
647         getstringfield(L, table, "image", def.imagename);
648         getstringfield(L, table, "cookresult_item", def.cookresult_item);
649         getfloatfield(L, table, "furnace_cooktime", def.furnace_cooktime);
650         getfloatfield(L, table, "furnace_burntime", def.furnace_burntime);
651         def.usable = getboolfield_default(L, table, "usable", got_on_use);
652         getboolfield(L, table, "liquids_pointable", def.liquids_pointable);
653         def.dropcount = getintfield_default(L, table, "dropcount", def.dropcount);
654         def.stack_max = getintfield_default(L, table, "stack_max", def.stack_max);
655
656         // If an on_drop callback is defined, force dropcount to 1
657         if (got_on_drop)
658                 def.dropcount = 1;
659
660         // Register it
661         craftitemdef->registerCraftItem(name, def);
662
663         lua_pushvalue(L, table);
664         scriptapi_add_craftitem(L, name);
665
666         return 0; /* number of results */
667 }
668
669 // register_node(name, {lots of stuff})
670 static int l_register_node(lua_State *L)
671 {
672         const char *name = luaL_checkstring(L, 1);
673         infostream<<"register_node: "<<name<<std::endl;
674         luaL_checktype(L, 2, LUA_TTABLE);
675         int nodedef_table = 2;
676
677         // Get server from registry
678         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
679         Server *server = (Server*)lua_touserdata(L, -1);
680         // And get the writable node definition manager from the server
681         IWritableNodeDefManager *nodedef =
682                         server->getWritableNodeDefManager();
683         
684         // Get default node definition from registry
685         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
686         int nodedef_default = lua_gettop(L);
687
688         /*
689                 Add to minetest.registered_nodes with default as metatable
690         */
691         
692         // Get the node definition table given as parameter
693         lua_pushvalue(L, nodedef_table);
694
695         // Set __index to point to itself
696         lua_pushvalue(L, -1);
697         lua_setfield(L, -2, "__index");
698
699         // Set nodedef_default as metatable for the definition
700         lua_pushvalue(L, nodedef_default);
701         lua_setmetatable(L, nodedef_table);
702         
703         // minetest.registered_nodes[name] = nodedef
704         lua_getglobal(L, "minetest");
705         lua_getfield(L, -1, "registered_nodes");
706         luaL_checktype(L, -1, LUA_TTABLE);
707         lua_pushstring(L, name);
708         lua_pushvalue(L, nodedef_table);
709         lua_settable(L, -3);
710
711         /*
712                 Create definition
713         */
714         
715         ContentFeatures f;
716
717         // Default to getting the corresponding NodeItem when dug
718         f.dug_item = std::string("NodeItem \"")+name+"\" 1";
719         
720         // Default to unknown_block.png as all textures
721         f.setAllTextures("unknown_block.png");
722
723         /*
724                 Read definiton from Lua
725         */
726
727         f.name = name;
728         
729         /* Visual definition */
730
731         f.drawtype = (NodeDrawType)getenumfield(L, nodedef_table, "drawtype", es_DrawType,
732                         NDT_NORMAL);
733         getfloatfield(L, nodedef_table, "visual_scale", f.visual_scale);
734
735         lua_getfield(L, nodedef_table, "tile_images");
736         if(lua_istable(L, -1)){
737                 int table = lua_gettop(L);
738                 lua_pushnil(L);
739                 int i = 0;
740                 while(lua_next(L, table) != 0){
741                         // key at index -2 and value at index -1
742                         if(lua_isstring(L, -1))
743                                 f.tname_tiles[i] = lua_tostring(L, -1);
744                         else
745                                 f.tname_tiles[i] = "";
746                         // removes value, keeps key for next iteration
747                         lua_pop(L, 1);
748                         i++;
749                         if(i==6){
750                                 lua_pop(L, 1);
751                                 break;
752                         }
753                 }
754                 // Copy last value to all remaining textures
755                 if(i >= 1){
756                         std::string lastname = f.tname_tiles[i-1];
757                         while(i < 6){
758                                 f.tname_tiles[i] = lastname;
759                                 i++;
760                         }
761                 }
762         }
763         lua_pop(L, 1);
764
765         getstringfield(L, nodedef_table, "inventory_image", f.tname_inventory);
766
767         lua_getfield(L, nodedef_table, "special_materials");
768         if(lua_istable(L, -1)){
769                 int table = lua_gettop(L);
770                 lua_pushnil(L);
771                 int i = 0;
772                 while(lua_next(L, table) != 0){
773                         // key at index -2 and value at index -1
774                         int smtable = lua_gettop(L);
775                         std::string tname = getstringfield_default(
776                                         L, smtable, "image", "");
777                         bool backface_culling = getboolfield_default(
778                                         L, smtable, "backface_culling", true);
779                         MaterialSpec mspec(tname, backface_culling);
780                         f.setSpecialMaterial(i, mspec);
781                         // removes value, keeps key for next iteration
782                         lua_pop(L, 1);
783                         i++;
784                         if(i==6){
785                                 lua_pop(L, 1);
786                                 break;
787                         }
788                 }
789         }
790         lua_pop(L, 1);
791
792         f.alpha = getintfield_default(L, nodedef_table, "alpha", 255);
793
794         /* Other stuff */
795         
796         lua_getfield(L, nodedef_table, "post_effect_color");
797         if(!lua_isnil(L, -1))
798                 f.post_effect_color = readARGB8(L, -1);
799         lua_pop(L, 1);
800
801         f.param_type = (ContentParamType)getenumfield(L, nodedef_table, "paramtype",
802                         es_ContentParamType, CPT_NONE);
803         
804         // True for all ground-like things like stone and mud, false for eg. trees
805         getboolfield(L, nodedef_table, "is_ground_content", f.is_ground_content);
806         getboolfield(L, nodedef_table, "light_propagates", f.light_propagates);
807         getboolfield(L, nodedef_table, "sunlight_propagates", f.sunlight_propagates);
808         // This is used for collision detection.
809         // Also for general solidness queries.
810         getboolfield(L, nodedef_table, "walkable", f.walkable);
811         // Player can point to these
812         getboolfield(L, nodedef_table, "pointable", f.pointable);
813         // Player can dig these
814         getboolfield(L, nodedef_table, "diggable", f.diggable);
815         // Player can climb these
816         getboolfield(L, nodedef_table, "climbable", f.climbable);
817         // Player can build on these
818         getboolfield(L, nodedef_table, "buildable_to", f.buildable_to);
819         // If true, param2 is set to direction when placed. Used for torches.
820         // NOTE: the direction format is quite inefficient and should be changed
821         getboolfield(L, nodedef_table, "wall_mounted", f.wall_mounted);
822         // Whether this content type often contains mineral.
823         // Used for texture atlas creation.
824         // Currently only enabled for CONTENT_STONE.
825         getboolfield(L, nodedef_table, "often_contains_mineral", f.often_contains_mineral);
826         // Inventory item string as which the node appears in inventory when dug.
827         // Mineral overrides this.
828         getstringfield(L, nodedef_table, "dug_item", f.dug_item);
829         // Extra dug item and its rarity
830         getstringfield(L, nodedef_table, "extra_dug_item", f.extra_dug_item);
831         // Usual get interval for extra dug item
832         getintfield(L, nodedef_table, "extra_dug_item_rarity", f.extra_dug_item_rarity);
833         // Metadata name of node (eg. "furnace")
834         getstringfield(L, nodedef_table, "metadata_name", f.metadata_name);
835         // Whether the node is non-liquid, source liquid or flowing liquid
836         f.liquid_type = (LiquidType)getenumfield(L, nodedef_table, "liquidtype",
837                         es_LiquidType, LIQUID_NONE);
838         // If the content is liquid, this is the flowing version of the liquid.
839         getstringfield(L, nodedef_table, "liquid_alternative_flowing",
840                         f.liquid_alternative_flowing);
841         // If the content is liquid, this is the source version of the liquid.
842         getstringfield(L, nodedef_table, "liquid_alternative_source",
843                         f.liquid_alternative_source);
844         // Viscosity for fluid flow, ranging from 1 to 7, with
845         // 1 giving almost instantaneous propagation and 7 being
846         // the slowest possible
847         f.liquid_viscosity = getintfield_default(L, nodedef_table,
848                         "liquid_viscosity", f.liquid_viscosity);
849         // Amount of light the node emits
850         f.light_source = getintfield_default(L, nodedef_table,
851                         "light_source", f.light_source);
852         f.damage_per_second = getintfield_default(L, nodedef_table,
853                         "damage_per_second", f.damage_per_second);
854         
855         lua_getfield(L, nodedef_table, "selection_box");
856         if(lua_istable(L, -1)){
857                 f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
858                                 es_NodeBoxType, NODEBOX_REGULAR);
859
860                 lua_getfield(L, -1, "fixed");
861                 if(lua_istable(L, -1))
862                         f.selection_box.fixed = read_aabbox3df32(L, -1, BS);
863                 lua_pop(L, 1);
864
865                 lua_getfield(L, -1, "wall_top");
866                 if(lua_istable(L, -1))
867                         f.selection_box.wall_top = read_aabbox3df32(L, -1, BS);
868                 lua_pop(L, 1);
869
870                 lua_getfield(L, -1, "wall_bottom");
871                 if(lua_istable(L, -1))
872                         f.selection_box.wall_bottom = read_aabbox3df32(L, -1, BS);
873                 lua_pop(L, 1);
874
875                 lua_getfield(L, -1, "wall_side");
876                 if(lua_istable(L, -1))
877                         f.selection_box.wall_side = read_aabbox3df32(L, -1, BS);
878                 lua_pop(L, 1);
879         }
880         lua_pop(L, 1);
881
882         lua_getfield(L, nodedef_table, "material");
883         if(lua_istable(L, -1)){
884                 f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
885                                 es_Diggability, DIGGABLE_NORMAL);
886                 
887                 getfloatfield(L, -1, "constant_time", f.material.constant_time);
888                 getfloatfield(L, -1, "weight", f.material.weight);
889                 getfloatfield(L, -1, "crackiness", f.material.crackiness);
890                 getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
891                 getfloatfield(L, -1, "cuttability", f.material.cuttability);
892                 getfloatfield(L, -1, "flammability", f.material.flammability);
893         }
894         lua_pop(L, 1);
895
896         getstringfield(L, nodedef_table, "cookresult_item", f.cookresult_item);
897         getfloatfield(L, nodedef_table, "furnace_cooktime", f.furnace_cooktime);
898         getfloatfield(L, nodedef_table, "furnace_burntime", f.furnace_burntime);
899         
900         /*
901                 Register it
902         */
903         
904         nodedef->set(name, f);
905         
906         return 0; /* number of results */
907 }
908
909 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
910 static int l_register_craft(lua_State *L)
911 {
912         infostream<<"register_craft"<<std::endl;
913         luaL_checktype(L, 1, LUA_TTABLE);
914         int table0 = 1;
915
916         // Get server from registry
917         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
918         Server *server = (Server*)lua_touserdata(L, -1);
919         // And get the writable craft definition manager from the server
920         IWritableCraftDefManager *craftdef =
921                         server->getWritableCraftDefManager();
922         
923         std::string output;
924         int width = 0;
925         std::vector<std::string> input;
926
927         lua_getfield(L, table0, "output");
928         luaL_checktype(L, -1, LUA_TSTRING);
929         if(lua_isstring(L, -1))
930                 output = lua_tostring(L, -1);
931         lua_pop(L, 1);
932
933         lua_getfield(L, table0, "recipe");
934         luaL_checktype(L, -1, LUA_TTABLE);
935         if(lua_istable(L, -1)){
936                 int table1 = lua_gettop(L);
937                 lua_pushnil(L);
938                 int rowcount = 0;
939                 while(lua_next(L, table1) != 0){
940                         int colcount = 0;
941                         // key at index -2 and value at index -1
942                         luaL_checktype(L, -1, LUA_TTABLE);
943                         if(lua_istable(L, -1)){
944                                 int table2 = lua_gettop(L);
945                                 lua_pushnil(L);
946                                 while(lua_next(L, table2) != 0){
947                                         // key at index -2 and value at index -1
948                                         luaL_checktype(L, -1, LUA_TSTRING);
949                                         input.push_back(lua_tostring(L, -1));
950                                         // removes value, keeps key for next iteration
951                                         lua_pop(L, 1);
952                                         colcount++;
953                                 }
954                         }
955                         if(rowcount == 0){
956                                 width = colcount;
957                         } else {
958                                 if(colcount != width){
959                                         script_error(L, "error: %s\n", "Invalid crafting recipe");
960                                 }
961                         }
962                         // removes value, keeps key for next iteration
963                         lua_pop(L, 1);
964                         rowcount++;
965                 }
966         }
967         lua_pop(L, 1);
968
969         CraftDefinition def(output, width, input);
970         craftdef->registerCraft(def);
971
972         return 0; /* number of results */
973 }
974
975 // setting_get(name)
976 static int l_setting_get(lua_State *L)
977 {
978         const char *name = luaL_checkstring(L, 1);
979         try{
980                 std::string value = g_settings->get(name);
981                 lua_pushstring(L, value.c_str());
982         } catch(SettingNotFoundException &e){
983                 lua_pushnil(L);
984         }
985         return 1;
986 }
987
988 // setting_getbool(name)
989 static int l_setting_getbool(lua_State *L)
990 {
991         const char *name = luaL_checkstring(L, 1);
992         try{
993                 bool value = g_settings->getBool(name);
994                 lua_pushboolean(L, value);
995         } catch(SettingNotFoundException &e){
996                 lua_pushnil(L);
997         }
998         return 1;
999 }
1000
1001 // chat_send_all(text)
1002 static int l_chat_send_all(lua_State *L)
1003 {
1004         const char *text = luaL_checkstring(L, 1);
1005         // Get server from registry
1006         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1007         Server *server = (Server*)lua_touserdata(L, -1);
1008         // Send
1009         server->notifyPlayers(narrow_to_wide(text));
1010         return 0;
1011 }
1012
1013 // chat_send_player(name, text)
1014 static int l_chat_send_player(lua_State *L)
1015 {
1016         const char *name = luaL_checkstring(L, 1);
1017         const char *text = luaL_checkstring(L, 2);
1018         // Get server from registry
1019         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1020         Server *server = (Server*)lua_touserdata(L, -1);
1021         // Send
1022         server->notifyPlayer(name, narrow_to_wide(text));
1023         return 0;
1024 }
1025
1026 // get_player_privs(name, text)
1027 static int l_get_player_privs(lua_State *L)
1028 {
1029         const char *name = luaL_checkstring(L, 1);
1030         // Get server from registry
1031         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1032         Server *server = (Server*)lua_touserdata(L, -1);
1033         // Do it
1034         lua_newtable(L);
1035         int table = lua_gettop(L);
1036         u64 privs_i = server->getPlayerAuthPrivs(name);
1037         // Special case for the "name" setting (local player / server owner)
1038         if(name == g_settings->get("name"))
1039                 privs_i = PRIV_ALL;
1040         std::set<std::string> privs_s = privsToSet(privs_i);
1041         for(std::set<std::string>::const_iterator
1042                         i = privs_s.begin(); i != privs_s.end(); i++){
1043                 lua_pushboolean(L, true);
1044                 lua_setfield(L, table, i->c_str());
1045         }
1046         lua_pushvalue(L, table);
1047         return 1;
1048 }
1049
1050 static const struct luaL_Reg minetest_f [] = {
1051         {"register_nodedef_defaults", l_register_nodedef_defaults},
1052         {"register_entity", l_register_entity},
1053         {"register_tool", l_register_tool},
1054         {"register_craftitem", l_register_craftitem},
1055         {"register_node", l_register_node},
1056         {"register_craft", l_register_craft},
1057         {"register_abm", l_register_abm},
1058         {"setting_get", l_setting_get},
1059         {"setting_getbool", l_setting_getbool},
1060         {"chat_send_all", l_chat_send_all},
1061         {"chat_send_player", l_chat_send_player},
1062         {"get_player_privs", l_get_player_privs},
1063         {NULL, NULL}
1064 };
1065
1066 /*
1067         LuaEntity functions
1068 */
1069
1070 static const struct luaL_Reg minetest_entity_m [] = {
1071         {NULL, NULL}
1072 };
1073
1074 /*
1075         Getters for stuff in main tables
1076 */
1077
1078 static void objectref_get(lua_State *L, u16 id)
1079 {
1080         // Get minetest.object_refs[i]
1081         lua_getglobal(L, "minetest");
1082         lua_getfield(L, -1, "object_refs");
1083         luaL_checktype(L, -1, LUA_TTABLE);
1084         lua_pushnumber(L, id);
1085         lua_gettable(L, -2);
1086         lua_remove(L, -2); // object_refs
1087         lua_remove(L, -2); // minetest
1088 }
1089
1090 static void luaentity_get(lua_State *L, u16 id)
1091 {
1092         // Get minetest.luaentities[i]
1093         lua_getglobal(L, "minetest");
1094         lua_getfield(L, -1, "luaentities");
1095         luaL_checktype(L, -1, LUA_TTABLE);
1096         lua_pushnumber(L, id);
1097         lua_gettable(L, -2);
1098         lua_remove(L, -2); // luaentities
1099         lua_remove(L, -2); // minetest
1100 }
1101
1102 /*
1103         Reference wrappers
1104 */
1105
1106 #define method(class, name) {#name, class::l_##name}
1107
1108 /*
1109         NodeMetaRef
1110 */
1111
1112 class NodeMetaRef
1113 {
1114 private:
1115         v3s16 m_p;
1116         ServerEnvironment *m_env;
1117
1118         static const char className[];
1119         static const luaL_reg methods[];
1120
1121         static NodeMetaRef *checkobject(lua_State *L, int narg)
1122         {
1123                 luaL_checktype(L, narg, LUA_TUSERDATA);
1124                 void *ud = luaL_checkudata(L, narg, className);
1125                 if(!ud) luaL_typerror(L, narg, className);
1126                 return *(NodeMetaRef**)ud;  // unbox pointer
1127         }
1128         
1129         static NodeMetadata* getmeta(NodeMetaRef *ref)
1130         {
1131                 NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p);
1132                 return meta;
1133         }
1134
1135         /*static IGenericNodeMetadata* getgenericmeta(NodeMetaRef *ref)
1136         {
1137                 NodeMetadata *meta = getmeta(ref);
1138                 if(meta == NULL)
1139                         return NULL;
1140                 if(meta->typeId() != NODEMETA_GENERIC)
1141                         return NULL;
1142                 return (IGenericNodeMetadata*)meta;
1143         }*/
1144
1145         static void reportMetadataChange(NodeMetaRef *ref)
1146         {
1147                 // Inform other things that the metadata has changed
1148                 v3s16 blockpos = getNodeBlockPos(ref->m_p);
1149                 MapEditEvent event;
1150                 event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
1151                 event.p = blockpos;
1152                 ref->m_env->getMap().dispatchEvent(&event);
1153                 // Set the block to be saved
1154                 MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos);
1155                 if(block)
1156                         block->raiseModified(MOD_STATE_WRITE_NEEDED,
1157                                         "NodeMetaRef::reportMetadataChange");
1158         }
1159         
1160         // Exported functions
1161         
1162         // garbage collector
1163         static int gc_object(lua_State *L) {
1164                 NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1));
1165                 delete o;
1166                 return 0;
1167         }
1168
1169         // get_type(self)
1170         static int l_get_type(lua_State *L)
1171         {
1172                 NodeMetaRef *ref = checkobject(L, 1);
1173                 NodeMetadata *meta = getmeta(ref);
1174                 if(meta == NULL){
1175                         lua_pushnil(L);
1176                         return 1;
1177                 }
1178                 // Do it
1179                 lua_pushstring(L, meta->typeName());
1180                 return 1;
1181         }
1182
1183         // allows_text_input(self)
1184         static int l_allows_text_input(lua_State *L)
1185         {
1186                 NodeMetaRef *ref = checkobject(L, 1);
1187                 NodeMetadata *meta = getmeta(ref);
1188                 if(meta == NULL) return 0;
1189                 // Do it
1190                 lua_pushboolean(L, meta->allowsTextInput());
1191                 return 1;
1192         }
1193
1194         // set_text(self, text)
1195         static int l_set_text(lua_State *L)
1196         {
1197                 NodeMetaRef *ref = checkobject(L, 1);
1198                 NodeMetadata *meta = getmeta(ref);
1199                 if(meta == NULL) return 0;
1200                 // Do it
1201                 std::string text = lua_tostring(L, 2);
1202                 meta->setText(text);
1203                 reportMetadataChange(ref);
1204                 return 0;
1205         }
1206
1207         // get_text(self)
1208         static int l_get_text(lua_State *L)
1209         {
1210                 NodeMetaRef *ref = checkobject(L, 1);
1211                 NodeMetadata *meta = getmeta(ref);
1212                 if(meta == NULL) return 0;
1213                 // Do it
1214                 std::string text = meta->getText();
1215                 lua_pushstring(L, text.c_str());
1216                 return 1;
1217         }
1218
1219         // get_owner(self)
1220         static int l_get_owner(lua_State *L)
1221         {
1222                 NodeMetaRef *ref = checkobject(L, 1);
1223                 NodeMetadata *meta = getmeta(ref);
1224                 if(meta == NULL) return 0;
1225                 // Do it
1226                 std::string owner = meta->getOwner();
1227                 lua_pushstring(L, owner.c_str());
1228                 return 1;
1229         }
1230
1231         /* IGenericNodeMetadata interface */
1232         
1233         // set_infotext(self, text)
1234         static int l_set_infotext(lua_State *L)
1235         {
1236                 infostream<<__FUNCTION_NAME<<std::endl;
1237                 NodeMetaRef *ref = checkobject(L, 1);
1238                 NodeMetadata *meta = getmeta(ref);
1239                 if(meta == NULL) return 0;
1240                 // Do it
1241                 std::string text = lua_tostring(L, 2);
1242                 meta->setInfoText(text);
1243                 reportMetadataChange(ref);
1244                 return 0;
1245         }
1246
1247         // inventory_set_list(self, name, {item1, item2, ...})
1248         static int l_inventory_set_list(lua_State *L)
1249         {
1250                 NodeMetaRef *ref = checkobject(L, 1);
1251                 NodeMetadata *meta = getmeta(ref);
1252                 if(meta == NULL) return 0;
1253                 // Do it
1254                 Inventory *inv = meta->getInventory();
1255                 std::string name = lua_tostring(L, 2);
1256                 // If nil, delete list
1257                 if(lua_isnil(L, 3)){
1258                         inv->deleteList(name);
1259                         return 0;
1260                 }
1261                 // Otherwise set list
1262                 std::list<std::string> items;
1263                 luaL_checktype(L, 3, LUA_TTABLE);
1264                 int table = 3;
1265                 lua_pushnil(L);
1266                 infostream<<"items: ";
1267                 while(lua_next(L, table) != 0){
1268                         // key at index -2 and value at index -1
1269                         luaL_checktype(L, -1, LUA_TSTRING);
1270                         std::string itemstring = lua_tostring(L, -1);
1271                         infostream<<"\""<<itemstring<<"\" ";
1272                         items.push_back(itemstring);
1273                         // removes value, keeps key for next iteration
1274                         lua_pop(L, 1);
1275                 }
1276                 infostream<<std::endl;
1277                 InventoryList *invlist = inv->addList(name, items.size());
1278                 int index = 0;
1279                 for(std::list<std::string>::const_iterator
1280                                 i = items.begin(); i != items.end(); i++){
1281                         const std::string &itemstring = *i;
1282                         InventoryItem *newitem = NULL;
1283                         if(itemstring != "")
1284                                 newitem = InventoryItem::deSerialize(itemstring,
1285                                                 ref->m_env->getGameDef());
1286                         InventoryItem *olditem = invlist->changeItem(index, newitem);
1287                         delete olditem;
1288                         index++;
1289                 }
1290                 reportMetadataChange(ref);
1291                 return 0;
1292         }
1293
1294         // inventory_get_list(self, name)
1295         static int l_inventory_get_list(lua_State *L)
1296         {
1297                 NodeMetaRef *ref = checkobject(L, 1);
1298                 NodeMetadata *meta = getmeta(ref);
1299                 if(meta == NULL) return 0;
1300                 // Do it
1301                 Inventory *inv = meta->getInventory();
1302                 std::string name = lua_tostring(L, 2);
1303                 InventoryList *invlist = inv->getList(name);
1304                 if(invlist == NULL){
1305                         lua_pushnil(L);
1306                         return 1;
1307                 }
1308                 // Get the table insert function
1309                 lua_getglobal(L, "table");
1310                 lua_getfield(L, -1, "insert");
1311                 int table_insert = lua_gettop(L);
1312                 // Create and fill table
1313                 lua_newtable(L);
1314                 int table = lua_gettop(L);
1315                 for(u32 i=0; i<invlist->getSize(); i++){
1316                         InventoryItem *item = invlist->getItem(i);
1317                         lua_pushvalue(L, table_insert);
1318                         lua_pushvalue(L, table);
1319                         if(item == NULL){
1320                                 lua_pushnil(L);
1321                         } else {
1322                                 lua_pushstring(L, item->getItemString().c_str());
1323                         }
1324                         if(lua_pcall(L, 2, 0, 0))
1325                                 script_error(L, "error: %s\n", lua_tostring(L, -1));
1326                 }
1327                 return 1;
1328         }
1329
1330         // set_inventory_draw_spec(self, text)
1331         static int l_set_inventory_draw_spec(lua_State *L)
1332         {
1333                 NodeMetaRef *ref = checkobject(L, 1);
1334                 NodeMetadata *meta = getmeta(ref);
1335                 if(meta == NULL) return 0;
1336                 // Do it
1337                 std::string text = lua_tostring(L, 2);
1338                 meta->setInventoryDrawSpec(text);
1339                 reportMetadataChange(ref);
1340                 return 0;
1341         }
1342
1343         // set_allow_text_input(self, text)
1344         static int l_set_allow_text_input(lua_State *L)
1345         {
1346                 NodeMetaRef *ref = checkobject(L, 1);
1347                 NodeMetadata *meta = getmeta(ref);
1348                 if(meta == NULL) return 0;
1349                 // Do it
1350                 bool b = lua_toboolean(L, 2);
1351                 meta->setAllowTextInput(b);
1352                 reportMetadataChange(ref);
1353                 return 0;
1354         }
1355
1356         // set_allow_removal(self, text)
1357         static int l_set_allow_removal(lua_State *L)
1358         {
1359                 NodeMetaRef *ref = checkobject(L, 1);
1360                 NodeMetadata *meta = getmeta(ref);
1361                 if(meta == NULL) return 0;
1362                 // Do it
1363                 bool b = lua_toboolean(L, 2);
1364                 meta->setRemovalDisabled(!b);
1365                 reportMetadataChange(ref);
1366                 return 0;
1367         }
1368
1369         // set_enforce_owner(self, text)
1370         static int l_set_enforce_owner(lua_State *L)
1371         {
1372                 NodeMetaRef *ref = checkobject(L, 1);
1373                 NodeMetadata *meta = getmeta(ref);
1374                 if(meta == NULL) return 0;
1375                 // Do it
1376                 bool b = lua_toboolean(L, 2);
1377                 meta->setEnforceOwner(b);
1378                 reportMetadataChange(ref);
1379                 return 0;
1380         }
1381
1382         // is_inventory_modified(self)
1383         static int l_is_inventory_modified(lua_State *L)
1384         {
1385                 NodeMetaRef *ref = checkobject(L, 1);
1386                 NodeMetadata *meta = getmeta(ref);
1387                 if(meta == NULL) return 0;
1388                 // Do it
1389                 lua_pushboolean(L, meta->isInventoryModified());
1390                 return 1;
1391         }
1392
1393         // reset_inventory_modified(self)
1394         static int l_reset_inventory_modified(lua_State *L)
1395         {
1396                 NodeMetaRef *ref = checkobject(L, 1);
1397                 NodeMetadata *meta = getmeta(ref);
1398                 if(meta == NULL) return 0;
1399                 // Do it
1400                 meta->resetInventoryModified();
1401                 reportMetadataChange(ref);
1402                 return 0;
1403         }
1404
1405         // is_text_modified(self)
1406         static int l_is_text_modified(lua_State *L)
1407         {
1408                 NodeMetaRef *ref = checkobject(L, 1);
1409                 NodeMetadata *meta = getmeta(ref);
1410                 if(meta == NULL) return 0;
1411                 // Do it
1412                 lua_pushboolean(L, meta->isTextModified());
1413                 return 1;
1414         }
1415
1416         // reset_text_modified(self)
1417         static int l_reset_text_modified(lua_State *L)
1418         {
1419                 NodeMetaRef *ref = checkobject(L, 1);
1420                 NodeMetadata *meta = getmeta(ref);
1421                 if(meta == NULL) return 0;
1422                 // Do it
1423                 meta->resetTextModified();
1424                 reportMetadataChange(ref);
1425                 return 0;
1426         }
1427
1428         // set_string(self, name, var)
1429         static int l_set_string(lua_State *L)
1430         {
1431                 NodeMetaRef *ref = checkobject(L, 1);
1432                 NodeMetadata *meta = getmeta(ref);
1433                 if(meta == NULL) return 0;
1434                 // Do it
1435                 std::string name = lua_tostring(L, 2);
1436                 size_t len = 0;
1437                 const char *s = lua_tolstring(L, 3, &len);
1438                 std::string str(s, len);
1439                 meta->setString(name, str);
1440                 reportMetadataChange(ref);
1441                 return 0;
1442         }
1443
1444         // get_string(self, name)
1445         static int l_get_string(lua_State *L)
1446         {
1447                 NodeMetaRef *ref = checkobject(L, 1);
1448                 NodeMetadata *meta = getmeta(ref);
1449                 if(meta == NULL) return 0;
1450                 // Do it
1451                 std::string name = lua_tostring(L, 2);
1452                 std::string str = meta->getString(name);
1453                 lua_pushlstring(L, str.c_str(), str.size());
1454                 return 1;
1455         }
1456
1457 public:
1458         NodeMetaRef(v3s16 p, ServerEnvironment *env):
1459                 m_p(p),
1460                 m_env(env)
1461         {
1462         }
1463
1464         ~NodeMetaRef()
1465         {
1466         }
1467
1468         // Creates an NodeMetaRef and leaves it on top of stack
1469         // Not callable from Lua; all references are created on the C side.
1470         static void create(lua_State *L, v3s16 p, ServerEnvironment *env)
1471         {
1472                 NodeMetaRef *o = new NodeMetaRef(p, env);
1473                 //infostream<<"NodeMetaRef::create: o="<<o<<std::endl;
1474                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1475                 luaL_getmetatable(L, className);
1476                 lua_setmetatable(L, -2);
1477         }
1478
1479         static void Register(lua_State *L)
1480         {
1481                 lua_newtable(L);
1482                 int methodtable = lua_gettop(L);
1483                 luaL_newmetatable(L, className);
1484                 int metatable = lua_gettop(L);
1485
1486                 lua_pushliteral(L, "__metatable");
1487                 lua_pushvalue(L, methodtable);
1488                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
1489
1490                 lua_pushliteral(L, "__index");
1491                 lua_pushvalue(L, methodtable);
1492                 lua_settable(L, metatable);
1493
1494                 lua_pushliteral(L, "__gc");
1495                 lua_pushcfunction(L, gc_object);
1496                 lua_settable(L, metatable);
1497
1498                 lua_pop(L, 1);  // drop metatable
1499
1500                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
1501                 lua_pop(L, 1);  // drop methodtable
1502
1503                 // Cannot be created from Lua
1504                 //lua_register(L, className, create_object);
1505         }
1506 };
1507 const char NodeMetaRef::className[] = "NodeMetaRef";
1508 const luaL_reg NodeMetaRef::methods[] = {
1509         method(NodeMetaRef, get_type),
1510         method(NodeMetaRef, allows_text_input),
1511         method(NodeMetaRef, set_text),
1512         method(NodeMetaRef, get_text),
1513         method(NodeMetaRef, get_owner),
1514         method(NodeMetaRef, set_infotext),
1515         method(NodeMetaRef, inventory_set_list),
1516         method(NodeMetaRef, inventory_get_list),
1517         method(NodeMetaRef, set_inventory_draw_spec),
1518         method(NodeMetaRef, set_allow_text_input),
1519         method(NodeMetaRef, set_allow_removal),
1520         method(NodeMetaRef, set_enforce_owner),
1521         method(NodeMetaRef, is_inventory_modified),
1522         method(NodeMetaRef, reset_inventory_modified),
1523         method(NodeMetaRef, is_text_modified),
1524         method(NodeMetaRef, reset_text_modified),
1525         method(NodeMetaRef, set_string),
1526         method(NodeMetaRef, get_string),
1527         {0,0}
1528 };
1529
1530 /*
1531         ObjectRef
1532 */
1533
1534 class ObjectRef
1535 {
1536 private:
1537         ServerActiveObject *m_object;
1538
1539         static const char className[];
1540         static const luaL_reg methods[];
1541
1542         static ObjectRef *checkobject(lua_State *L, int narg)
1543         {
1544                 luaL_checktype(L, narg, LUA_TUSERDATA);
1545                 void *ud = luaL_checkudata(L, narg, className);
1546                 if(!ud) luaL_typerror(L, narg, className);
1547                 return *(ObjectRef**)ud;  // unbox pointer
1548         }
1549         
1550         static ServerActiveObject* getobject(ObjectRef *ref)
1551         {
1552                 ServerActiveObject *co = ref->m_object;
1553                 return co;
1554         }
1555         
1556         static LuaEntitySAO* getluaobject(ObjectRef *ref)
1557         {
1558                 ServerActiveObject *obj = getobject(ref);
1559                 if(obj == NULL)
1560                         return NULL;
1561                 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
1562                         return NULL;
1563                 return (LuaEntitySAO*)obj;
1564         }
1565         
1566         static ServerRemotePlayer* getplayer(ObjectRef *ref)
1567         {
1568                 ServerActiveObject *obj = getobject(ref);
1569                 if(obj == NULL)
1570                         return NULL;
1571                 if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
1572                         return NULL;
1573                 return static_cast<ServerRemotePlayer*>(obj);
1574         }
1575         
1576         // Exported functions
1577         
1578         // garbage collector
1579         static int gc_object(lua_State *L) {
1580                 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
1581                 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
1582                 delete o;
1583                 return 0;
1584         }
1585
1586         // remove(self)
1587         static int l_remove(lua_State *L)
1588         {
1589                 ObjectRef *ref = checkobject(L, 1);
1590                 ServerActiveObject *co = getobject(ref);
1591                 if(co == NULL) return 0;
1592                 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
1593                 co->m_removed = true;
1594                 return 0;
1595         }
1596         
1597         // getpos(self)
1598         // returns: {x=num, y=num, z=num}
1599         static int l_getpos(lua_State *L)
1600         {
1601                 ObjectRef *ref = checkobject(L, 1);
1602                 ServerActiveObject *co = getobject(ref);
1603                 if(co == NULL) return 0;
1604                 v3f pos = co->getBasePosition() / BS;
1605                 lua_newtable(L);
1606                 lua_pushnumber(L, pos.X);
1607                 lua_setfield(L, -2, "x");
1608                 lua_pushnumber(L, pos.Y);
1609                 lua_setfield(L, -2, "y");
1610                 lua_pushnumber(L, pos.Z);
1611                 lua_setfield(L, -2, "z");
1612                 return 1;
1613         }
1614         
1615         // setpos(self, pos)
1616         static int l_setpos(lua_State *L)
1617         {
1618                 ObjectRef *ref = checkobject(L, 1);
1619                 //LuaEntitySAO *co = getluaobject(ref);
1620                 ServerActiveObject *co = getobject(ref);
1621                 if(co == NULL) return 0;
1622                 // pos
1623                 v3f pos = readFloatPos(L, 2);
1624                 // Do it
1625                 co->setPos(pos);
1626                 return 0;
1627         }
1628         
1629         // moveto(self, pos, continuous=false)
1630         static int l_moveto(lua_State *L)
1631         {
1632                 ObjectRef *ref = checkobject(L, 1);
1633                 //LuaEntitySAO *co = getluaobject(ref);
1634                 ServerActiveObject *co = getobject(ref);
1635                 if(co == NULL) return 0;
1636                 // pos
1637                 v3f pos = readFloatPos(L, 2);
1638                 // continuous
1639                 bool continuous = lua_toboolean(L, 3);
1640                 // Do it
1641                 co->moveTo(pos, continuous);
1642                 return 0;
1643         }
1644
1645         // setvelocity(self, velocity)
1646         static int l_setvelocity(lua_State *L)
1647         {
1648                 ObjectRef *ref = checkobject(L, 1);
1649                 LuaEntitySAO *co = getluaobject(ref);
1650                 if(co == NULL) return 0;
1651                 // pos
1652                 v3f pos = readFloatPos(L, 2);
1653                 // Do it
1654                 co->setVelocity(pos);
1655                 return 0;
1656         }
1657         
1658         // setacceleration(self, acceleration)
1659         static int l_setacceleration(lua_State *L)
1660         {
1661                 ObjectRef *ref = checkobject(L, 1);
1662                 LuaEntitySAO *co = getluaobject(ref);
1663                 if(co == NULL) return 0;
1664                 // pos
1665                 v3f pos = readFloatPos(L, 2);
1666                 // Do it
1667                 co->setAcceleration(pos);
1668                 return 0;
1669         }
1670         
1671         // getacceleration(self)
1672         static int l_getacceleration(lua_State *L)
1673         {
1674                 ObjectRef *ref = checkobject(L, 1);
1675                 LuaEntitySAO *co = getluaobject(ref);
1676                 if(co == NULL) return 0;
1677                 // Do it
1678                 v3f v = co->getAcceleration();
1679                 pushFloatPos(L, v);
1680                 return 1;
1681         }
1682         
1683         // add_to_inventory(self, itemstring)
1684         // returns: true if item was added, (false, "reason") otherwise
1685         static int l_add_to_inventory(lua_State *L)
1686         {
1687                 ObjectRef *ref = checkobject(L, 1);
1688                 luaL_checkstring(L, 2);
1689                 ServerActiveObject *co = getobject(ref);
1690                 if(co == NULL) return 0;
1691                 // itemstring
1692                 const char *itemstring = lua_tostring(L, 2);
1693                 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
1694                                 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1695                 // Do it
1696                 std::istringstream is(itemstring, std::ios::binary);
1697                 ServerEnvironment *env = co->getEnv();
1698                 assert(env);
1699                 IGameDef *gamedef = env->getGameDef();
1700                 try{
1701                         InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1702                         if(item->getCount() == 0)
1703                                 item->setCount(1);
1704                         bool added = co->addToInventory(item);
1705                         // Return
1706                         lua_pushboolean(L, added);
1707                         if(!added)
1708                                 lua_pushstring(L, "does not fit");
1709                         return 2;
1710                 } catch(SerializationError &e){
1711                         // Return
1712                         lua_pushboolean(L, false);
1713                         lua_pushstring(L, (std::string("Invalid item: ")
1714                                         + e.what()).c_str());
1715                         return 2;
1716                 }
1717         }
1718
1719         // add_to_inventory_later(self, itemstring)
1720         // returns: nil
1721         static int l_add_to_inventory_later(lua_State *L)
1722         {
1723                 ObjectRef *ref = checkobject(L, 1);
1724                 luaL_checkstring(L, 2);
1725                 ServerActiveObject *co = getobject(ref);
1726                 if(co == NULL) return 0;
1727                 // itemstring
1728                 const char *itemstring = lua_tostring(L, 2);
1729                 infostream<<"ObjectRef::l_add_to_inventory_later(): id="<<co->getId()
1730                                 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1731                 // Do it
1732                 std::istringstream is(itemstring, std::ios::binary);
1733                 ServerEnvironment *env = co->getEnv();
1734                 assert(env);
1735                 IGameDef *gamedef = env->getGameDef();
1736                 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1737                 infostream<<"item="<<env<<std::endl;
1738                 co->addToInventoryLater(item);
1739                 // Return
1740                 return 0;
1741         }
1742
1743         // get_hp(self)
1744         // returns: number of hitpoints (2 * number of hearts)
1745         // 0 if not applicable to this type of object
1746         static int l_get_hp(lua_State *L)
1747         {
1748                 ObjectRef *ref = checkobject(L, 1);
1749                 ServerActiveObject *co = getobject(ref);
1750                 if(co == NULL) return 0;
1751                 int hp = co->getHP();
1752                 infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
1753                                 <<" hp="<<hp<<std::endl;
1754                 // Return
1755                 lua_pushnumber(L, hp);
1756                 return 1;
1757         }
1758
1759         // set_hp(self, hp)
1760         // hp = number of hitpoints (2 * number of hearts)
1761         // returns: nil
1762         static int l_set_hp(lua_State *L)
1763         {
1764                 ObjectRef *ref = checkobject(L, 1);
1765                 luaL_checknumber(L, 2);
1766                 ServerActiveObject *co = getobject(ref);
1767                 if(co == NULL) return 0;
1768                 int hp = lua_tonumber(L, 2);
1769                 infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
1770                                 <<" hp="<<hp<<std::endl;
1771                 // Do it
1772                 co->setHP(hp);
1773                 // Return
1774                 return 0;
1775         }
1776
1777         // settexturemod(self, mod)
1778         static int l_settexturemod(lua_State *L)
1779         {
1780                 ObjectRef *ref = checkobject(L, 1);
1781                 LuaEntitySAO *co = getluaobject(ref);
1782                 if(co == NULL) return 0;
1783                 // Do it
1784                 std::string mod = lua_tostring(L, 2);
1785                 co->setTextureMod(mod);
1786                 return 0;
1787         }
1788         
1789         // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
1790         //           select_horiz_by_yawpitch=false)
1791         static int l_setsprite(lua_State *L)
1792         {
1793                 ObjectRef *ref = checkobject(L, 1);
1794                 LuaEntitySAO *co = getluaobject(ref);
1795                 if(co == NULL) return 0;
1796                 // Do it
1797                 v2s16 p(0,0);
1798                 if(!lua_isnil(L, 2))
1799                         p = read_v2s16(L, 2);
1800                 int num_frames = 1;
1801                 if(!lua_isnil(L, 3))
1802                         num_frames = lua_tonumber(L, 3);
1803                 float framelength = 0.2;
1804                 if(!lua_isnil(L, 4))
1805                         framelength = lua_tonumber(L, 4);
1806                 bool select_horiz_by_yawpitch = false;
1807                 if(!lua_isnil(L, 5))
1808                         select_horiz_by_yawpitch = lua_toboolean(L, 5);
1809                 co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
1810                 return 0;
1811         }
1812         
1813 public:
1814         ObjectRef(ServerActiveObject *object):
1815                 m_object(object)
1816         {
1817                 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
1818         }
1819
1820         ~ObjectRef()
1821         {
1822                 /*if(m_object)
1823                         infostream<<"ObjectRef destructing for id="
1824                                         <<m_object->getId()<<std::endl;
1825                 else
1826                         infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
1827         }
1828
1829         // Creates an ObjectRef and leaves it on top of stack
1830         // Not callable from Lua; all references are created on the C side.
1831         static void create(lua_State *L, ServerActiveObject *object)
1832         {
1833                 ObjectRef *o = new ObjectRef(object);
1834                 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
1835                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1836                 luaL_getmetatable(L, className);
1837                 lua_setmetatable(L, -2);
1838         }
1839
1840         static void set_null(lua_State *L)
1841         {
1842                 ObjectRef *o = checkobject(L, -1);
1843                 o->m_object = NULL;
1844         }
1845         
1846         static void Register(lua_State *L)
1847         {
1848                 lua_newtable(L);
1849                 int methodtable = lua_gettop(L);
1850                 luaL_newmetatable(L, className);
1851                 int metatable = lua_gettop(L);
1852
1853                 lua_pushliteral(L, "__metatable");
1854                 lua_pushvalue(L, methodtable);
1855                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
1856
1857                 lua_pushliteral(L, "__index");
1858                 lua_pushvalue(L, methodtable);
1859                 lua_settable(L, metatable);
1860
1861                 lua_pushliteral(L, "__gc");
1862                 lua_pushcfunction(L, gc_object);
1863                 lua_settable(L, metatable);
1864
1865                 lua_pop(L, 1);  // drop metatable
1866
1867                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
1868                 lua_pop(L, 1);  // drop methodtable
1869
1870                 // Cannot be created from Lua
1871                 //lua_register(L, className, create_object);
1872         }
1873 };
1874 const char ObjectRef::className[] = "ObjectRef";
1875 const luaL_reg ObjectRef::methods[] = {
1876         method(ObjectRef, remove),
1877         method(ObjectRef, getpos),
1878         method(ObjectRef, setpos),
1879         method(ObjectRef, moveto),
1880         method(ObjectRef, setvelocity),
1881         method(ObjectRef, setacceleration),
1882         method(ObjectRef, add_to_inventory),
1883         method(ObjectRef, add_to_inventory_later),
1884         method(ObjectRef, get_hp),
1885         method(ObjectRef, set_hp),
1886         method(ObjectRef, settexturemod),
1887         method(ObjectRef, setsprite),
1888         {0,0}
1889 };
1890
1891 // Creates a new anonymous reference if id=0
1892 static void objectref_get_or_create(lua_State *L,
1893                 ServerActiveObject *cobj)
1894 {
1895         if(cobj->getId() == 0){
1896                 ObjectRef::create(L, cobj);
1897         } else {
1898                 objectref_get(L, cobj->getId());
1899         }
1900 }
1901
1902 /*
1903         EnvRef
1904 */
1905
1906 class EnvRef
1907 {
1908 private:
1909         ServerEnvironment *m_env;
1910
1911         static const char className[];
1912         static const luaL_reg methods[];
1913
1914         static EnvRef *checkobject(lua_State *L, int narg)
1915         {
1916                 luaL_checktype(L, narg, LUA_TUSERDATA);
1917                 void *ud = luaL_checkudata(L, narg, className);
1918                 if(!ud) luaL_typerror(L, narg, className);
1919                 return *(EnvRef**)ud;  // unbox pointer
1920         }
1921         
1922         // Exported functions
1923
1924         // EnvRef:add_node(pos, node)
1925         // pos = {x=num, y=num, z=num}
1926         static int l_add_node(lua_State *L)
1927         {
1928                 //infostream<<"EnvRef::l_add_node()"<<std::endl;
1929                 EnvRef *o = checkobject(L, 1);
1930                 ServerEnvironment *env = o->m_env;
1931                 if(env == NULL) return 0;
1932                 // pos
1933                 v3s16 pos = readpos(L, 2);
1934                 // content
1935                 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
1936                 // Do it
1937                 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
1938                 lua_pushboolean(L, succeeded);
1939                 return 1;
1940         }
1941
1942         // EnvRef:remove_node(pos)
1943         // pos = {x=num, y=num, z=num}
1944         static int l_remove_node(lua_State *L)
1945         {
1946                 //infostream<<"EnvRef::l_remove_node()"<<std::endl;
1947                 EnvRef *o = checkobject(L, 1);
1948                 ServerEnvironment *env = o->m_env;
1949                 if(env == NULL) return 0;
1950                 // pos
1951                 v3s16 pos = readpos(L, 2);
1952                 // Do it
1953                 bool succeeded = env->getMap().removeNodeWithEvent(pos);
1954                 lua_pushboolean(L, succeeded);
1955                 return 1;
1956         }
1957
1958         // EnvRef:get_node(pos)
1959         // pos = {x=num, y=num, z=num}
1960         static int l_get_node(lua_State *L)
1961         {
1962                 //infostream<<"EnvRef::l_get_node()"<<std::endl;
1963                 EnvRef *o = checkobject(L, 1);
1964                 ServerEnvironment *env = o->m_env;
1965                 if(env == NULL) return 0;
1966                 // pos
1967                 v3s16 pos = readpos(L, 2);
1968                 // Do it
1969                 MapNode n = env->getMap().getNodeNoEx(pos);
1970                 // Return node
1971                 pushnode(L, n, env->getGameDef()->ndef());
1972                 return 1;
1973         }
1974
1975         // EnvRef:add_luaentity(pos, entityname)
1976         // pos = {x=num, y=num, z=num}
1977         static int l_add_luaentity(lua_State *L)
1978         {
1979                 //infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
1980                 EnvRef *o = checkobject(L, 1);
1981                 ServerEnvironment *env = o->m_env;
1982                 if(env == NULL) return 0;
1983                 // pos
1984                 v3f pos = readFloatPos(L, 2);
1985                 // content
1986                 const char *name = lua_tostring(L, 3);
1987                 // Do it
1988                 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
1989                 env->addActiveObject(obj);
1990                 return 0;
1991         }
1992
1993         // EnvRef:add_item(pos, inventorystring)
1994         // pos = {x=num, y=num, z=num}
1995         static int l_add_item(lua_State *L)
1996         {
1997                 infostream<<"EnvRef::l_add_item()"<<std::endl;
1998                 EnvRef *o = checkobject(L, 1);
1999                 ServerEnvironment *env = o->m_env;
2000                 if(env == NULL) return 0;
2001                 // pos
2002                 v3f pos = readFloatPos(L, 2);
2003                 // inventorystring
2004                 const char *inventorystring = lua_tostring(L, 3);
2005                 // Do it
2006                 ServerActiveObject *obj = new ItemSAO(env, pos, inventorystring);
2007                 env->addActiveObject(obj);
2008                 return 0;
2009         }
2010
2011         // EnvRef:add_rat(pos)
2012         // pos = {x=num, y=num, z=num}
2013         static int l_add_rat(lua_State *L)
2014         {
2015                 infostream<<"EnvRef::l_add_rat()"<<std::endl;
2016                 EnvRef *o = checkobject(L, 1);
2017                 ServerEnvironment *env = o->m_env;
2018                 if(env == NULL) return 0;
2019                 // pos
2020                 v3f pos = readFloatPos(L, 2);
2021                 // Do it
2022                 ServerActiveObject *obj = new RatSAO(env, pos);
2023                 env->addActiveObject(obj);
2024                 return 0;
2025         }
2026
2027         // EnvRef:add_firefly(pos)
2028         // pos = {x=num, y=num, z=num}
2029         static int l_add_firefly(lua_State *L)
2030         {
2031                 infostream<<"EnvRef::l_add_firefly()"<<std::endl;
2032                 EnvRef *o = checkobject(L, 1);
2033                 ServerEnvironment *env = o->m_env;
2034                 if(env == NULL) return 0;
2035                 // pos
2036                 v3f pos = readFloatPos(L, 2);
2037                 // Do it
2038                 ServerActiveObject *obj = new FireflySAO(env, pos);
2039                 env->addActiveObject(obj);
2040                 return 0;
2041         }
2042
2043         // EnvRef:get_meta(pos)
2044         static int l_get_meta(lua_State *L)
2045         {
2046                 //infostream<<"EnvRef::l_get_meta()"<<std::endl;
2047                 EnvRef *o = checkobject(L, 1);
2048                 ServerEnvironment *env = o->m_env;
2049                 if(env == NULL) return 0;
2050                 // Do it
2051                 v3s16 p = readpos(L, 2);
2052                 NodeMetaRef::create(L, p, env);
2053                 return 1;
2054         }
2055
2056         // EnvRef:get_player_by_name(name)
2057         static int l_get_player_by_name(lua_State *L)
2058         {
2059                 EnvRef *o = checkobject(L, 1);
2060                 ServerEnvironment *env = o->m_env;
2061                 if(env == NULL) return 0;
2062                 // Do it
2063                 const char *name = lua_tostring(L, 2);
2064                 ServerRemotePlayer *player =
2065                                 static_cast<ServerRemotePlayer*>(env->getPlayer(name));
2066                 if(player == NULL){
2067                         lua_pushnil(L);
2068                         return 1;
2069                 }
2070                 // Put player on stack
2071                 objectref_get_or_create(L, player);
2072                 return 1;
2073         }
2074
2075         static int gc_object(lua_State *L) {
2076                 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
2077                 delete o;
2078                 return 0;
2079         }
2080
2081 public:
2082         EnvRef(ServerEnvironment *env):
2083                 m_env(env)
2084         {
2085                 infostream<<"EnvRef created"<<std::endl;
2086         }
2087
2088         ~EnvRef()
2089         {
2090                 infostream<<"EnvRef destructing"<<std::endl;
2091         }
2092
2093         // Creates an EnvRef and leaves it on top of stack
2094         // Not callable from Lua; all references are created on the C side.
2095         static void create(lua_State *L, ServerEnvironment *env)
2096         {
2097                 EnvRef *o = new EnvRef(env);
2098                 //infostream<<"EnvRef::create: o="<<o<<std::endl;
2099                 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2100                 luaL_getmetatable(L, className);
2101                 lua_setmetatable(L, -2);
2102         }
2103
2104         static void set_null(lua_State *L)
2105         {
2106                 EnvRef *o = checkobject(L, -1);
2107                 o->m_env = NULL;
2108         }
2109         
2110         static void Register(lua_State *L)
2111         {
2112                 lua_newtable(L);
2113                 int methodtable = lua_gettop(L);
2114                 luaL_newmetatable(L, className);
2115                 int metatable = lua_gettop(L);
2116
2117                 lua_pushliteral(L, "__metatable");
2118                 lua_pushvalue(L, methodtable);
2119                 lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
2120
2121                 lua_pushliteral(L, "__index");
2122                 lua_pushvalue(L, methodtable);
2123                 lua_settable(L, metatable);
2124
2125                 lua_pushliteral(L, "__gc");
2126                 lua_pushcfunction(L, gc_object);
2127                 lua_settable(L, metatable);
2128
2129                 lua_pop(L, 1);  // drop metatable
2130
2131                 luaL_openlib(L, 0, methods, 0);  // fill methodtable
2132                 lua_pop(L, 1);  // drop methodtable
2133
2134                 // Cannot be created from Lua
2135                 //lua_register(L, className, create_object);
2136         }
2137 };
2138 const char EnvRef::className[] = "EnvRef";
2139 const luaL_reg EnvRef::methods[] = {
2140         method(EnvRef, add_node),
2141         method(EnvRef, remove_node),
2142         method(EnvRef, get_node),
2143         method(EnvRef, add_luaentity),
2144         method(EnvRef, add_item),
2145         method(EnvRef, add_rat),
2146         method(EnvRef, add_firefly),
2147         method(EnvRef, get_meta),
2148         method(EnvRef, get_player_by_name),
2149         {0,0}
2150 };
2151
2152 /*
2153         Main export function
2154 */
2155
2156 void scriptapi_export(lua_State *L, Server *server)
2157 {
2158         realitycheck(L);
2159         assert(lua_checkstack(L, 20));
2160         infostream<<"scriptapi_export"<<std::endl;
2161         StackUnroller stack_unroller(L);
2162
2163         // Store server as light userdata in registry
2164         lua_pushlightuserdata(L, server);
2165         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
2166
2167         // Store nil as minetest_nodedef_defaults in registry
2168         lua_pushnil(L);
2169         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
2170         
2171         // Register global functions in table minetest
2172         lua_newtable(L);
2173         luaL_register(L, NULL, minetest_f);
2174         lua_setglobal(L, "minetest");
2175         
2176         // Get the main minetest table
2177         lua_getglobal(L, "minetest");
2178
2179         // Add tables to minetest
2180         
2181         lua_newtable(L);
2182         lua_setfield(L, -2, "registered_nodes");
2183         lua_newtable(L);
2184         lua_setfield(L, -2, "registered_entities");
2185         lua_newtable(L);
2186         lua_setfield(L, -2, "registered_craftitems");
2187         lua_newtable(L);
2188         lua_setfield(L, -2, "registered_abms");
2189         
2190         lua_newtable(L);
2191         lua_setfield(L, -2, "object_refs");
2192         lua_newtable(L);
2193         lua_setfield(L, -2, "luaentities");
2194
2195         // Create entity prototype
2196         luaL_newmetatable(L, "minetest.entity");
2197         // metatable.__index = metatable
2198         lua_pushvalue(L, -1); // Duplicate metatable
2199         lua_setfield(L, -2, "__index");
2200         // Put functions in metatable
2201         luaL_register(L, NULL, minetest_entity_m);
2202         // Put other stuff in metatable
2203         
2204         // Register reference wrappers
2205         NodeMetaRef::Register(L);
2206         EnvRef::Register(L);
2207         ObjectRef::Register(L);
2208 }
2209
2210 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
2211 {
2212         realitycheck(L);
2213         assert(lua_checkstack(L, 20));
2214         infostream<<"scriptapi_add_environment"<<std::endl;
2215         StackUnroller stack_unroller(L);
2216
2217         // Create EnvRef on stack
2218         EnvRef::create(L, env);
2219         int envref = lua_gettop(L);
2220
2221         // minetest.env = envref
2222         lua_getglobal(L, "minetest");
2223         luaL_checktype(L, -1, LUA_TTABLE);
2224         lua_pushvalue(L, envref);
2225         lua_setfield(L, -2, "env");
2226
2227         // Store environment as light userdata in registry
2228         lua_pushlightuserdata(L, env);
2229         lua_setfield(L, LUA_REGISTRYINDEX, "minetest_env");
2230
2231         /* Add ActiveBlockModifiers to environment */
2232
2233         // Get minetest.registered_abms
2234         lua_getglobal(L, "minetest");
2235         lua_getfield(L, -1, "registered_abms");
2236         luaL_checktype(L, -1, LUA_TTABLE);
2237         int registered_abms = lua_gettop(L);
2238         
2239         if(lua_istable(L, registered_abms)){
2240                 int table = lua_gettop(L);
2241                 lua_pushnil(L);
2242                 while(lua_next(L, table) != 0){
2243                         // key at index -2 and value at index -1
2244                         int id = lua_tonumber(L, -2);
2245                         int current_abm = lua_gettop(L);
2246
2247                         std::set<std::string> trigger_contents;
2248                         lua_getfield(L, current_abm, "nodenames");
2249                         if(lua_istable(L, -1)){
2250                                 int table = lua_gettop(L);
2251                                 lua_pushnil(L);
2252                                 while(lua_next(L, table) != 0){
2253                                         // key at index -2 and value at index -1
2254                                         luaL_checktype(L, -1, LUA_TSTRING);
2255                                         trigger_contents.insert(lua_tostring(L, -1));
2256                                         // removes value, keeps key for next iteration
2257                                         lua_pop(L, 1);
2258                                 }
2259                         }
2260                         lua_pop(L, 1);
2261
2262                         float trigger_interval = 10.0;
2263                         getfloatfield(L, current_abm, "interval", trigger_interval);
2264
2265                         int trigger_chance = 50;
2266                         getintfield(L, current_abm, "chance", trigger_chance);
2267
2268                         LuaABM *abm = new LuaABM(L, id, trigger_contents,
2269                                         trigger_interval, trigger_chance);
2270                         
2271                         env->addActiveBlockModifier(abm);
2272
2273                         // removes value, keeps key for next iteration
2274                         lua_pop(L, 1);
2275                 }
2276         }
2277         lua_pop(L, 1);
2278 }
2279
2280 #if 0
2281 // Dump stack top with the dump2 function
2282 static void dump2(lua_State *L, const char *name)
2283 {
2284         // Dump object (debug)
2285         lua_getglobal(L, "dump2");
2286         luaL_checktype(L, -1, LUA_TFUNCTION);
2287         lua_pushvalue(L, -2); // Get previous stack top as first parameter
2288         lua_pushstring(L, name);
2289         if(lua_pcall(L, 2, 0, 0))
2290                 script_error(L, "error: %s\n", lua_tostring(L, -1));
2291 }
2292 #endif
2293
2294 /*
2295         object_reference
2296 */
2297
2298 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
2299 {
2300         realitycheck(L);
2301         assert(lua_checkstack(L, 20));
2302         //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
2303         StackUnroller stack_unroller(L);
2304
2305         // Create object on stack
2306         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
2307         int object = lua_gettop(L);
2308
2309         // Get minetest.object_refs table
2310         lua_getglobal(L, "minetest");
2311         lua_getfield(L, -1, "object_refs");
2312         luaL_checktype(L, -1, LUA_TTABLE);
2313         int objectstable = lua_gettop(L);
2314         
2315         // object_refs[id] = object
2316         lua_pushnumber(L, cobj->getId()); // Push id
2317         lua_pushvalue(L, object); // Copy object to top of stack
2318         lua_settable(L, objectstable);
2319 }
2320
2321 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
2322 {
2323         realitycheck(L);
2324         assert(lua_checkstack(L, 20));
2325         //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
2326         StackUnroller stack_unroller(L);
2327
2328         // Get minetest.object_refs table
2329         lua_getglobal(L, "minetest");
2330         lua_getfield(L, -1, "object_refs");
2331         luaL_checktype(L, -1, LUA_TTABLE);
2332         int objectstable = lua_gettop(L);
2333         
2334         // Get object_refs[id]
2335         lua_pushnumber(L, cobj->getId()); // Push id
2336         lua_gettable(L, objectstable);
2337         // Set object reference to NULL
2338         ObjectRef::set_null(L);
2339         lua_pop(L, 1); // pop object
2340
2341         // Set object_refs[id] = nil
2342         lua_pushnumber(L, cobj->getId()); // Push id
2343         lua_pushnil(L);
2344         lua_settable(L, objectstable);
2345 }
2346
2347 bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
2348                 const std::string &message)
2349 {
2350         realitycheck(L);
2351         assert(lua_checkstack(L, 20));
2352         StackUnroller stack_unroller(L);
2353
2354         // Get minetest.registered_on_chat_messages
2355         lua_getglobal(L, "minetest");
2356         lua_getfield(L, -1, "registered_on_chat_messages");
2357         luaL_checktype(L, -1, LUA_TTABLE);
2358         int table = lua_gettop(L);
2359         // Foreach
2360         lua_pushnil(L);
2361         while(lua_next(L, table) != 0){
2362                 // key at index -2 and value at index -1
2363                 luaL_checktype(L, -1, LUA_TFUNCTION);
2364                 // Call function
2365                 lua_pushstring(L, name.c_str());
2366                 lua_pushstring(L, message.c_str());
2367                 if(lua_pcall(L, 2, 1, 0))
2368                         script_error(L, "error: %s\n", lua_tostring(L, -1));
2369                 bool ate = lua_toboolean(L, -1);
2370                 lua_pop(L, 1);
2371                 if(ate)
2372                         return true;
2373                 // value removed, keep key for next iteration
2374         }
2375         return false;
2376 }
2377
2378 /*
2379         misc
2380 */
2381
2382 void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
2383 {
2384         realitycheck(L);
2385         assert(lua_checkstack(L, 20));
2386         StackUnroller stack_unroller(L);
2387
2388         // Get minetest.registered_on_newplayers
2389         lua_getglobal(L, "minetest");
2390         lua_getfield(L, -1, "registered_on_newplayers");
2391         luaL_checktype(L, -1, LUA_TTABLE);
2392         int table = lua_gettop(L);
2393         // Foreach
2394         lua_pushnil(L);
2395         while(lua_next(L, table) != 0){
2396                 // key at index -2 and value at index -1
2397                 luaL_checktype(L, -1, LUA_TFUNCTION);
2398                 // Call function
2399                 objectref_get_or_create(L, player);
2400                 if(lua_pcall(L, 1, 0, 0))
2401                         script_error(L, "error: %s\n", lua_tostring(L, -1));
2402                 // value removed, keep key for next iteration
2403         }
2404 }
2405 bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
2406 {
2407         realitycheck(L);
2408         assert(lua_checkstack(L, 20));
2409         StackUnroller stack_unroller(L);
2410
2411         bool positioning_handled_by_some = false;
2412
2413         // Get minetest.registered_on_respawnplayers
2414         lua_getglobal(L, "minetest");
2415         lua_getfield(L, -1, "registered_on_respawnplayers");
2416         luaL_checktype(L, -1, LUA_TTABLE);
2417         int table = lua_gettop(L);
2418         // Foreach
2419         lua_pushnil(L);
2420         while(lua_next(L, table) != 0){
2421                 // key at index -2 and value at index -1
2422                 luaL_checktype(L, -1, LUA_TFUNCTION);
2423                 // Call function
2424                 objectref_get_or_create(L, player);
2425                 if(lua_pcall(L, 1, 1, 0))
2426                         script_error(L, "error: %s\n", lua_tostring(L, -1));
2427                 bool positioning_handled = lua_toboolean(L, -1);
2428                 lua_pop(L, 1);
2429                 if(positioning_handled)
2430                         positioning_handled_by_some = true;
2431                 // value removed, keep key for next iteration
2432         }
2433         return positioning_handled_by_some;
2434 }
2435
2436 /*
2437         craftitem
2438 */
2439
2440 static void pushPointedThing(lua_State *L, const PointedThing& pointed)
2441 {
2442         lua_newtable(L);
2443         if(pointed.type == POINTEDTHING_NODE)
2444         {
2445                 lua_pushstring(L, "node");
2446                 lua_setfield(L, -2, "type");
2447                 pushpos(L, pointed.node_undersurface);
2448                 lua_setfield(L, -2, "under");
2449                 pushpos(L, pointed.node_abovesurface);
2450                 lua_setfield(L, -2, "above");
2451         }
2452         else if(pointed.type == POINTEDTHING_OBJECT)
2453         {
2454                 lua_pushstring(L, "object");
2455                 lua_setfield(L, -2, "type");
2456                 objectref_get(L, pointed.object_id);
2457                 lua_setfield(L, -2, "ref");
2458         }
2459         else
2460         {
2461                 lua_pushstring(L, "nothing");
2462                 lua_setfield(L, -2, "type");
2463         }
2464 }
2465
2466 void scriptapi_add_craftitem(lua_State *L, const char *name)
2467 {
2468         StackUnroller stack_unroller(L);
2469         assert(lua_gettop(L) > 0);
2470
2471         // Set minetest.registered_craftitems[name] = table on top of stack
2472         lua_getglobal(L, "minetest");
2473         lua_getfield(L, -1, "registered_craftitems");
2474         luaL_checktype(L, -1, LUA_TTABLE);
2475         lua_pushvalue(L, -3); // push another reference to the table to be registered
2476         lua_setfield(L, -2, name); // set minetest.registered_craftitems[name]
2477 }
2478
2479 static bool get_craftitem_callback(lua_State *L, const char *name,
2480                 const char *callbackname)
2481 {
2482         // Get minetest.registered_craftitems[name][callbackname]
2483         // If that is nil or on error, return false and stack is unchanged
2484         // If that is a function, returns true and pushes the
2485         // function onto the stack
2486
2487         lua_getglobal(L, "minetest");
2488         lua_getfield(L, -1, "registered_craftitems");
2489         lua_remove(L, -2);
2490         luaL_checktype(L, -1, LUA_TTABLE);
2491         lua_getfield(L, -1, name);
2492         lua_remove(L, -2);
2493         // Should be a table
2494         if(lua_type(L, -1) != LUA_TTABLE)
2495         {
2496                 errorstream<<"CraftItem name \""<<name<<"\" not defined"<<std::endl;
2497                 lua_pop(L, 1);
2498                 return false;
2499         }
2500         lua_getfield(L, -1, callbackname);
2501         lua_remove(L, -2);
2502         // Should be a function or nil
2503         if(lua_type(L, -1) == LUA_TFUNCTION)
2504         {
2505                 return true;
2506         }
2507         else if(lua_isnil(L, -1))
2508         {
2509                 lua_pop(L, 1);
2510                 return false;
2511         }
2512         else
2513         {
2514                 errorstream<<"CraftItem name \""<<name<<"\" callback \""
2515                         <<callbackname<<" is not a function"<<std::endl;
2516                 lua_pop(L, 1);
2517                 return false;
2518         }
2519 }
2520
2521 bool scriptapi_craftitem_on_drop(lua_State *L, const char *name,
2522                 ServerActiveObject *dropper, v3f pos,
2523                 bool &callback_exists)
2524 {
2525         realitycheck(L);
2526         assert(lua_checkstack(L, 20));
2527         //infostream<<"scriptapi_craftitem_on_drop"<<std::endl;
2528         StackUnroller stack_unroller(L);
2529
2530         bool result = false;
2531         callback_exists = get_craftitem_callback(L, name, "on_drop");
2532         if(callback_exists)
2533         {
2534                 // Call function
2535                 lua_pushstring(L, name);
2536                 objectref_get_or_create(L, dropper);
2537                 pushFloatPos(L, pos);
2538                 if(lua_pcall(L, 3, 1, 0))
2539                         script_error(L, "error: %s\n", lua_tostring(L, -1));
2540                 result = lua_toboolean(L, -1);
2541         }
2542         return result;
2543 }
2544
2545 bool scriptapi_craftitem_on_place_on_ground(lua_State *L, const char *name,
2546                 ServerActiveObject *placer, v3f pos,
2547                 bool &callback_exists)
2548 {
2549         realitycheck(L);
2550         assert(lua_checkstack(L, 20));
2551         //infostream<<"scriptapi_craftitem_on_place_on_ground"<<std::endl;
2552         StackUnroller stack_unroller(L);
2553
2554         bool result = false;
2555         callback_exists = get_craftitem_callback(L, name, "on_place_on_ground");
2556         if(callback_exists)
2557         {
2558                 // Call function
2559                 lua_pushstring(L, name);
2560                 objectref_get_or_create(L, placer);
2561                 pushFloatPos(L, pos);
2562                 if(lua_pcall(L, 3, 1, 0))
2563                         script_error(L, "error: %s\n", lua_tostring(L, -1));
2564                 result = lua_toboolean(L, -1);
2565         }
2566         return result;
2567 }
2568
2569 bool scriptapi_craftitem_on_use(lua_State *L, const char *name,
2570                 ServerActiveObject *user, const PointedThing& pointed,
2571                 bool &callback_exists)
2572 {
2573         realitycheck(L);
2574         assert(lua_checkstack(L, 20));
2575         //infostream<<"scriptapi_craftitem_on_use"<<std::endl;
2576         StackUnroller stack_unroller(L);
2577
2578         bool result = false;
2579         callback_exists = get_craftitem_callback(L, name, "on_use");
2580         if(callback_exists)
2581         {
2582                 // Call function
2583                 lua_pushstring(L, name);
2584                 objectref_get_or_create(L, user);
2585                 pushPointedThing(L, pointed);
2586                 if(lua_pcall(L, 3, 1, 0))
2587                         script_error(L, "error: %s\n", lua_tostring(L, -1));
2588                 result = lua_toboolean(L, -1);
2589         }
2590         return result;
2591 }
2592
2593 /*
2594         environment
2595 */
2596
2597 void scriptapi_environment_step(lua_State *L, float dtime)
2598 {
2599         realitycheck(L);
2600         assert(lua_checkstack(L, 20));
2601         //infostream<<"scriptapi_environment_step"<<std::endl;
2602         StackUnroller stack_unroller(L);
2603
2604         // Get minetest.registered_globalsteps
2605         lua_getglobal(L, "minetest");
2606         lua_getfield(L, -1, "registered_globalsteps");
2607         luaL_checktype(L, -1, LUA_TTABLE);
2608         int table = lua_gettop(L);
2609         // Foreach
2610         lua_pushnil(L);
2611         while(lua_next(L, table) != 0){
2612                 // key at index -2 and value at index -1
2613                 luaL_checktype(L, -1, LUA_TFUNCTION);
2614                 // Call function
2615                 lua_pushnumber(L, dtime);
2616                 if(lua_pcall(L, 1, 0, 0))
2617                         script_error(L, "error: %s\n", lua_tostring(L, -1));
2618                 // value removed, keep key for next iteration
2619         }
2620 }
2621
2622 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
2623                 ServerActiveObject *placer)
2624 {
2625         realitycheck(L);
2626         assert(lua_checkstack(L, 20));
2627         //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
2628         StackUnroller stack_unroller(L);
2629
2630         // Get server from registry
2631         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
2632         Server *server = (Server*)lua_touserdata(L, -1);
2633         // And get the writable node definition manager from the server
2634         IWritableNodeDefManager *ndef =
2635                         server->getWritableNodeDefManager();
2636         
2637         // Get minetest.registered_on_placenodes
2638         lua_getglobal(L, "minetest");
2639         lua_getfield(L, -1, "registered_on_placenodes");
2640         luaL_checktype(L, -1, LUA_TTABLE);
2641         int table = lua_gettop(L);
2642         // Foreach
2643         lua_pushnil(L);
2644         while(lua_next(L, table) != 0){
2645                 // key at index -2 and value at index -1
2646                 luaL_checktype(L, -1, LUA_TFUNCTION);
2647                 // Call function
2648                 pushpos(L, p);
2649                 pushnode(L, newnode, ndef);
2650                 objectref_get_or_create(L, placer);
2651                 if(lua_pcall(L, 3, 0, 0))
2652                         script_error(L, "error: %s\n", lua_tostring(L, -1));
2653                 // value removed, keep key for next iteration
2654         }
2655 }
2656
2657 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
2658                 ServerActiveObject *digger)
2659 {
2660         realitycheck(L);
2661         assert(lua_checkstack(L, 20));
2662         //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
2663         StackUnroller stack_unroller(L);
2664
2665         // Get server from registry
2666         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
2667         Server *server = (Server*)lua_touserdata(L, -1);
2668         // And get the writable node definition manager from the server
2669         IWritableNodeDefManager *ndef =
2670                         server->getWritableNodeDefManager();
2671         
2672         // Get minetest.registered_on_dignodes
2673         lua_getglobal(L, "minetest");
2674         lua_getfield(L, -1, "registered_on_dignodes");
2675         luaL_checktype(L, -1, LUA_TTABLE);
2676         int table = lua_gettop(L);
2677         // Foreach
2678         lua_pushnil(L);
2679         while(lua_next(L, table) != 0){
2680                 // key at index -2 and value at index -1
2681                 luaL_checktype(L, -1, LUA_TFUNCTION);
2682                 // Call function
2683                 pushpos(L, p);
2684                 pushnode(L, oldnode, ndef);
2685                 objectref_get_or_create(L, digger);
2686                 if(lua_pcall(L, 3, 0, 0))
2687                         script_error(L, "error: %s\n", lua_tostring(L, -1));
2688                 // value removed, keep key for next iteration
2689         }
2690 }
2691
2692 void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
2693                 ServerActiveObject *puncher)
2694 {
2695         realitycheck(L);
2696         assert(lua_checkstack(L, 20));
2697         //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
2698         StackUnroller stack_unroller(L);
2699
2700         // Get server from registry
2701         lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
2702         Server *server = (Server*)lua_touserdata(L, -1);
2703         // And get the writable node definition manager from the server
2704         IWritableNodeDefManager *ndef =
2705                         server->getWritableNodeDefManager();
2706         
2707         // Get minetest.registered_on_punchnodes
2708         lua_getglobal(L, "minetest");
2709         lua_getfield(L, -1, "registered_on_punchnodes");
2710         luaL_checktype(L, -1, LUA_TTABLE);
2711         int table = lua_gettop(L);
2712         // Foreach
2713         lua_pushnil(L);
2714         while(lua_next(L, table) != 0){
2715                 // key at index -2 and value at index -1
2716                 luaL_checktype(L, -1, LUA_TFUNCTION);
2717                 // Call function
2718                 pushpos(L, p);
2719                 pushnode(L, node, ndef);
2720                 objectref_get_or_create(L, puncher);
2721                 if(lua_pcall(L, 3, 0, 0))
2722                         script_error(L, "error: %s\n", lua_tostring(L, -1));
2723                 // value removed, keep key for next iteration
2724         }
2725 }
2726
2727 void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
2728 {
2729         realitycheck(L);
2730         assert(lua_checkstack(L, 20));
2731         //infostream<<"scriptapi_environment_on_generated"<<std::endl;
2732         StackUnroller stack_unroller(L);
2733
2734         // Get minetest.registered_on_generateds
2735         lua_getglobal(L, "minetest");
2736         lua_getfield(L, -1, "registered_on_generateds");
2737         luaL_checktype(L, -1, LUA_TTABLE);
2738         int table = lua_gettop(L);
2739         // Foreach
2740         lua_pushnil(L);
2741         while(lua_next(L, table) != 0){
2742                 // key at index -2 and value at index -1
2743                 luaL_checktype(L, -1, LUA_TFUNCTION);
2744                 // Call function
2745                 pushpos(L, minp);
2746                 pushpos(L, maxp);
2747                 if(lua_pcall(L, 2, 0, 0))
2748                         script_error(L, "error: %s\n", lua_tostring(L, -1));
2749                 // value removed, keep key for next iteration
2750         }
2751 }
2752
2753 /*
2754         luaentity
2755 */
2756
2757 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
2758                 const std::string &staticdata)
2759 {
2760         realitycheck(L);
2761         assert(lua_checkstack(L, 20));
2762         infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
2763                         <<name<<"\""<<std::endl;
2764         StackUnroller stack_unroller(L);
2765         
2766         // Get minetest.registered_entities[name]
2767         lua_getglobal(L, "minetest");
2768         lua_getfield(L, -1, "registered_entities");
2769         luaL_checktype(L, -1, LUA_TTABLE);
2770         lua_pushstring(L, name);
2771         lua_gettable(L, -2);
2772         // Should be a table, which we will use as a prototype
2773         //luaL_checktype(L, -1, LUA_TTABLE);
2774         if(lua_type(L, -1) != LUA_TTABLE){
2775                 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
2776                 return false;
2777         }
2778         int prototype_table = lua_gettop(L);
2779         //dump2(L, "prototype_table");
2780         
2781         // Create entity object
2782         lua_newtable(L);
2783         int object = lua_gettop(L);
2784
2785         // Set object metatable
2786         lua_pushvalue(L, prototype_table);
2787         lua_setmetatable(L, -2);
2788         
2789         // Add object reference
2790         // This should be userdata with metatable ObjectRef
2791         objectref_get(L, id);
2792         luaL_checktype(L, -1, LUA_TUSERDATA);
2793         if(!luaL_checkudata(L, -1, "ObjectRef"))
2794                 luaL_typerror(L, -1, "ObjectRef");
2795         lua_setfield(L, -2, "object");
2796
2797         // minetest.luaentities[id] = object
2798         lua_getglobal(L, "minetest");
2799         lua_getfield(L, -1, "luaentities");
2800         luaL_checktype(L, -1, LUA_TTABLE);
2801         lua_pushnumber(L, id); // Push id
2802         lua_pushvalue(L, object); // Copy object to top of stack
2803         lua_settable(L, -3);
2804         
2805         // Get on_activate function
2806         lua_pushvalue(L, object);
2807         lua_getfield(L, -1, "on_activate");
2808         if(!lua_isnil(L, -1)){
2809                 luaL_checktype(L, -1, LUA_TFUNCTION);
2810                 lua_pushvalue(L, object); // self
2811                 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
2812                 // Call with 2 arguments, 0 results
2813                 if(lua_pcall(L, 2, 0, 0))
2814                         script_error(L, "error running function %s:on_activate: %s\n",
2815                                         name, lua_tostring(L, -1));
2816         }
2817         
2818         return true;
2819 }
2820
2821 void scriptapi_luaentity_rm(lua_State *L, u16 id)
2822 {
2823         realitycheck(L);
2824         assert(lua_checkstack(L, 20));
2825         infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
2826
2827         // Get minetest.luaentities table
2828         lua_getglobal(L, "minetest");
2829         lua_getfield(L, -1, "luaentities");
2830         luaL_checktype(L, -1, LUA_TTABLE);
2831         int objectstable = lua_gettop(L);
2832         
2833         // Set luaentities[id] = nil
2834         lua_pushnumber(L, id); // Push id
2835         lua_pushnil(L);
2836         lua_settable(L, objectstable);
2837         
2838         lua_pop(L, 2); // pop luaentities, minetest
2839 }
2840
2841 std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
2842 {
2843         realitycheck(L);
2844         assert(lua_checkstack(L, 20));
2845         infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
2846         StackUnroller stack_unroller(L);
2847
2848         // Get minetest.luaentities[id]
2849         luaentity_get(L, id);
2850         int object = lua_gettop(L);
2851         
2852         // Get get_staticdata function
2853         lua_pushvalue(L, object);
2854         lua_getfield(L, -1, "get_staticdata");
2855         if(lua_isnil(L, -1))
2856                 return "";
2857         
2858         luaL_checktype(L, -1, LUA_TFUNCTION);
2859         lua_pushvalue(L, object); // self
2860         // Call with 1 arguments, 1 results
2861         if(lua_pcall(L, 1, 1, 0))
2862                 script_error(L, "error running function get_staticdata: %s\n",
2863                                 lua_tostring(L, -1));
2864         
2865         size_t len=0;
2866         const char *s = lua_tolstring(L, -1, &len);
2867         return std::string(s, len);
2868 }
2869
2870 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
2871                 LuaEntityProperties *prop)
2872 {
2873         realitycheck(L);
2874         assert(lua_checkstack(L, 20));
2875         infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
2876         StackUnroller stack_unroller(L);
2877
2878         // Get minetest.luaentities[id]
2879         luaentity_get(L, id);
2880         //int object = lua_gettop(L);
2881
2882         /* Read stuff */
2883         
2884         getboolfield(L, -1, "physical", prop->physical);
2885
2886         getfloatfield(L, -1, "weight", prop->weight);
2887
2888         lua_getfield(L, -1, "collisionbox");
2889         if(lua_istable(L, -1))
2890                 prop->collisionbox = read_aabbox3df32(L, -1, 1.0);
2891         lua_pop(L, 1);
2892
2893         getstringfield(L, -1, "visual", prop->visual);
2894         
2895         lua_getfield(L, -1, "visual_size");
2896         if(lua_istable(L, -1))
2897                 prop->visual_size = read_v2f(L, -1);
2898         lua_pop(L, 1);
2899
2900         lua_getfield(L, -1, "textures");
2901         if(lua_istable(L, -1)){
2902                 prop->textures.clear();
2903                 int table = lua_gettop(L);
2904                 lua_pushnil(L);
2905                 while(lua_next(L, table) != 0){
2906                         // key at index -2 and value at index -1
2907                         if(lua_isstring(L, -1))
2908                                 prop->textures.push_back(lua_tostring(L, -1));
2909                         else
2910                                 prop->textures.push_back("");
2911                         // removes value, keeps key for next iteration
2912                         lua_pop(L, 1);
2913                 }
2914         }
2915         lua_pop(L, 1);
2916         
2917         lua_getfield(L, -1, "spritediv");
2918         if(lua_istable(L, -1))
2919                 prop->spritediv = read_v2s16(L, -1);
2920         lua_pop(L, 1);
2921
2922         lua_getfield(L, -1, "initial_sprite_basepos");
2923         if(lua_istable(L, -1))
2924                 prop->initial_sprite_basepos = read_v2s16(L, -1);
2925         lua_pop(L, 1);
2926 }
2927
2928 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
2929 {
2930         realitycheck(L);
2931         assert(lua_checkstack(L, 20));
2932         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
2933         StackUnroller stack_unroller(L);
2934
2935         // Get minetest.luaentities[id]
2936         luaentity_get(L, id);
2937         int object = lua_gettop(L);
2938         // State: object is at top of stack
2939         // Get step function
2940         lua_getfield(L, -1, "on_step");
2941         if(lua_isnil(L, -1))
2942                 return;
2943         luaL_checktype(L, -1, LUA_TFUNCTION);
2944         lua_pushvalue(L, object); // self
2945         lua_pushnumber(L, dtime); // dtime
2946         // Call with 2 arguments, 0 results
2947         if(lua_pcall(L, 2, 0, 0))
2948                 script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
2949 }
2950
2951 // Calls entity:on_punch(ObjectRef puncher)
2952 void scriptapi_luaentity_punch(lua_State *L, u16 id,
2953                 ServerActiveObject *puncher)
2954 {
2955         realitycheck(L);
2956         assert(lua_checkstack(L, 20));
2957         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
2958         StackUnroller stack_unroller(L);
2959
2960         // Get minetest.luaentities[id]
2961         luaentity_get(L, id);
2962         int object = lua_gettop(L);
2963         // State: object is at top of stack
2964         // Get function
2965         lua_getfield(L, -1, "on_punch");
2966         if(lua_isnil(L, -1))
2967                 return;
2968         luaL_checktype(L, -1, LUA_TFUNCTION);
2969         lua_pushvalue(L, object); // self
2970         objectref_get_or_create(L, puncher); // Clicker reference
2971         // Call with 2 arguments, 0 results
2972         if(lua_pcall(L, 2, 0, 0))
2973                 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
2974 }
2975
2976 // Calls entity:on_rightclick(ObjectRef clicker)
2977 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
2978                 ServerActiveObject *clicker)
2979 {
2980         realitycheck(L);
2981         assert(lua_checkstack(L, 20));
2982         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
2983         StackUnroller stack_unroller(L);
2984
2985         // Get minetest.luaentities[id]
2986         luaentity_get(L, id);
2987         int object = lua_gettop(L);
2988         // State: object is at top of stack
2989         // Get function
2990         lua_getfield(L, -1, "on_rightclick");
2991         if(lua_isnil(L, -1))
2992                 return;
2993         luaL_checktype(L, -1, LUA_TFUNCTION);
2994         lua_pushvalue(L, object); // self
2995         objectref_get_or_create(L, clicker); // Clicker reference
2996         // Call with 2 arguments, 0 results
2997         if(lua_pcall(L, 2, 0, 0))
2998                 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));
2999 }
3000