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