]> git.lizzy.rs Git - minetest.git/blob - src/scriptapi_object.cpp
Grow dirt_with_snow instead of dirt_with_grass if snow is above it
[minetest.git] / src / scriptapi_object.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "scriptapi.h"
21 #include "scriptapi_object.h"
22 #include "log.h"
23 #include "tool.h"
24 #include "scriptapi_types.h"
25 #include "scriptapi_inventory.h"
26 #include "scriptapi_item.h"
27 #include "scriptapi_entity.h"
28 #include "scriptapi_common.h"
29 #include "hud.h"
30
31
32 struct EnumString es_HudElementType[] =
33 {
34         {HUD_ELEM_IMAGE,     "image"},
35         {HUD_ELEM_TEXT,      "text"},
36         {HUD_ELEM_STATBAR,   "statbar"},
37         {HUD_ELEM_INVENTORY, "inventory"},
38         {0, NULL},
39 };
40
41 struct EnumString es_HudElementStat[] =
42 {
43         {HUD_STAT_POS,    "pos"},
44         {HUD_STAT_NAME,   "name"},
45         {HUD_STAT_SCALE,  "scale"},
46         {HUD_STAT_TEXT,   "text"},
47         {HUD_STAT_NUMBER, "number"},
48         {HUD_STAT_ITEM,   "item"},
49         {HUD_STAT_DIR,    "direction"},
50         {HUD_STAT_ALIGN,  "alignment"},
51         {HUD_STAT_OFFSET, "offset"},
52         {0, NULL},
53 };
54
55
56 /*
57         ObjectRef
58 */
59
60
61 ObjectRef* ObjectRef::checkobject(lua_State *L, int narg)
62 {
63         luaL_checktype(L, narg, LUA_TUSERDATA);
64         void *ud = luaL_checkudata(L, narg, className);
65         if(!ud) luaL_typerror(L, narg, className);
66         return *(ObjectRef**)ud;  // unbox pointer
67 }
68
69 ServerActiveObject* ObjectRef::getobject(ObjectRef *ref)
70 {
71         ServerActiveObject *co = ref->m_object;
72         return co;
73 }
74
75 LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
76 {
77         ServerActiveObject *obj = getobject(ref);
78         if(obj == NULL)
79                 return NULL;
80         if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
81                 return NULL;
82         return (LuaEntitySAO*)obj;
83 }
84
85 PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
86 {
87         ServerActiveObject *obj = getobject(ref);
88         if(obj == NULL)
89                 return NULL;
90         if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
91                 return NULL;
92         return (PlayerSAO*)obj;
93 }
94
95 Player* ObjectRef::getplayer(ObjectRef *ref)
96 {
97         PlayerSAO *playersao = getplayersao(ref);
98         if(playersao == NULL)
99                 return NULL;
100         return playersao->getPlayer();
101 }
102
103 // Exported functions
104
105 // garbage collector
106 int ObjectRef::gc_object(lua_State *L) {
107         ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
108         //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
109         delete o;
110         return 0;
111 }
112
113 // remove(self)
114 int ObjectRef::l_remove(lua_State *L)
115 {
116         ObjectRef *ref = checkobject(L, 1);
117         ServerActiveObject *co = getobject(ref);
118         if(co == NULL) return 0;
119         verbosestream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
120         co->m_removed = true;
121         return 0;
122 }
123
124 // getpos(self)
125 // returns: {x=num, y=num, z=num}
126 int ObjectRef::l_getpos(lua_State *L)
127 {
128         ObjectRef *ref = checkobject(L, 1);
129         ServerActiveObject *co = getobject(ref);
130         if(co == NULL) return 0;
131         v3f pos = co->getBasePosition() / BS;
132         lua_newtable(L);
133         lua_pushnumber(L, pos.X);
134         lua_setfield(L, -2, "x");
135         lua_pushnumber(L, pos.Y);
136         lua_setfield(L, -2, "y");
137         lua_pushnumber(L, pos.Z);
138         lua_setfield(L, -2, "z");
139         return 1;
140 }
141
142 // setpos(self, pos)
143 int ObjectRef::l_setpos(lua_State *L)
144 {
145         ObjectRef *ref = checkobject(L, 1);
146         //LuaEntitySAO *co = getluaobject(ref);
147         ServerActiveObject *co = getobject(ref);
148         if(co == NULL) return 0;
149         // pos
150         v3f pos = checkFloatPos(L, 2);
151         // Do it
152         co->setPos(pos);
153         return 0;
154 }
155
156 // moveto(self, pos, continuous=false)
157 int ObjectRef::l_moveto(lua_State *L)
158 {
159         ObjectRef *ref = checkobject(L, 1);
160         //LuaEntitySAO *co = getluaobject(ref);
161         ServerActiveObject *co = getobject(ref);
162         if(co == NULL) return 0;
163         // pos
164         v3f pos = checkFloatPos(L, 2);
165         // continuous
166         bool continuous = lua_toboolean(L, 3);
167         // Do it
168         co->moveTo(pos, continuous);
169         return 0;
170 }
171
172 // punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
173 int ObjectRef::l_punch(lua_State *L)
174 {
175         ObjectRef *ref = checkobject(L, 1);
176         ObjectRef *puncher_ref = checkobject(L, 2);
177         ServerActiveObject *co = getobject(ref);
178         ServerActiveObject *puncher = getobject(puncher_ref);
179         if(co == NULL) return 0;
180         if(puncher == NULL) return 0;
181         v3f dir;
182         if(lua_type(L, 5) != LUA_TTABLE)
183                 dir = co->getBasePosition() - puncher->getBasePosition();
184         else
185                 dir = read_v3f(L, 5);
186         float time_from_last_punch = 1000000;
187         if(lua_isnumber(L, 3))
188                 time_from_last_punch = lua_tonumber(L, 3);
189         ToolCapabilities toolcap = read_tool_capabilities(L, 4);
190         dir.normalize();
191         // Do it
192         co->punch(dir, &toolcap, puncher, time_from_last_punch);
193         return 0;
194 }
195
196 // right_click(self, clicker); clicker = an another ObjectRef
197 int ObjectRef::l_right_click(lua_State *L)
198 {
199         ObjectRef *ref = checkobject(L, 1);
200         ObjectRef *ref2 = checkobject(L, 2);
201         ServerActiveObject *co = getobject(ref);
202         ServerActiveObject *co2 = getobject(ref2);
203         if(co == NULL) return 0;
204         if(co2 == NULL) return 0;
205         // Do it
206         co->rightClick(co2);
207         return 0;
208 }
209
210 // set_hp(self, hp)
211 // hp = number of hitpoints (2 * number of hearts)
212 // returns: nil
213 int ObjectRef::l_set_hp(lua_State *L)
214 {
215         ObjectRef *ref = checkobject(L, 1);
216         luaL_checknumber(L, 2);
217         ServerActiveObject *co = getobject(ref);
218         if(co == NULL) return 0;
219         int hp = lua_tonumber(L, 2);
220         /*infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
221                         <<" hp="<<hp<<std::endl;*/
222         // Do it
223         co->setHP(hp);
224         // Return
225         return 0;
226 }
227
228 // get_hp(self)
229 // returns: number of hitpoints (2 * number of hearts)
230 // 0 if not applicable to this type of object
231 int ObjectRef::l_get_hp(lua_State *L)
232 {
233         ObjectRef *ref = checkobject(L, 1);
234         ServerActiveObject *co = getobject(ref);
235         if(co == NULL){
236                 // Default hp is 1
237                 lua_pushnumber(L, 1);
238                 return 1;
239         }
240         int hp = co->getHP();
241         /*infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
242                         <<" hp="<<hp<<std::endl;*/
243         // Return
244         lua_pushnumber(L, hp);
245         return 1;
246 }
247
248 // get_inventory(self)
249 int ObjectRef::l_get_inventory(lua_State *L)
250 {
251         ObjectRef *ref = checkobject(L, 1);
252         ServerActiveObject *co = getobject(ref);
253         if(co == NULL) return 0;
254         // Do it
255         InventoryLocation loc = co->getInventoryLocation();
256         if(get_server(L)->getInventory(loc) != NULL)
257                 InvRef::create(L, loc);
258         else
259                 lua_pushnil(L); // An object may have no inventory (nil)
260         return 1;
261 }
262
263 // get_wield_list(self)
264 int ObjectRef::l_get_wield_list(lua_State *L)
265 {
266         ObjectRef *ref = checkobject(L, 1);
267         ServerActiveObject *co = getobject(ref);
268         if(co == NULL) return 0;
269         // Do it
270         lua_pushstring(L, co->getWieldList().c_str());
271         return 1;
272 }
273
274 // get_wield_index(self)
275 int ObjectRef::l_get_wield_index(lua_State *L)
276 {
277         ObjectRef *ref = checkobject(L, 1);
278         ServerActiveObject *co = getobject(ref);
279         if(co == NULL) return 0;
280         // Do it
281         lua_pushinteger(L, co->getWieldIndex() + 1);
282         return 1;
283 }
284
285 // get_wielded_item(self)
286 int ObjectRef::l_get_wielded_item(lua_State *L)
287 {
288         ObjectRef *ref = checkobject(L, 1);
289         ServerActiveObject *co = getobject(ref);
290         if(co == NULL){
291                 // Empty ItemStack
292                 LuaItemStack::create(L, ItemStack());
293                 return 1;
294         }
295         // Do it
296         LuaItemStack::create(L, co->getWieldedItem());
297         return 1;
298 }
299
300 // set_wielded_item(self, itemstack or itemstring or table or nil)
301 int ObjectRef::l_set_wielded_item(lua_State *L)
302 {
303         ObjectRef *ref = checkobject(L, 1);
304         ServerActiveObject *co = getobject(ref);
305         if(co == NULL) return 0;
306         // Do it
307         ItemStack item = read_item(L, 2);
308         bool success = co->setWieldedItem(item);
309         lua_pushboolean(L, success);
310         return 1;
311 }
312
313 // set_armor_groups(self, groups)
314 int ObjectRef::l_set_armor_groups(lua_State *L)
315 {
316         ObjectRef *ref = checkobject(L, 1);
317         ServerActiveObject *co = getobject(ref);
318         if(co == NULL) return 0;
319         // Do it
320         ItemGroupList groups;
321         read_groups(L, 2, groups);
322         co->setArmorGroups(groups);
323         return 0;
324 }
325
326 // set_physics_override(self, physics_override_speed, physics_override_jump, physics_override_gravity)
327 int ObjectRef::l_set_physics_override(lua_State *L)
328 {
329         ObjectRef *ref = checkobject(L, 1);
330         PlayerSAO *co = (PlayerSAO *) getobject(ref);
331         if(co == NULL) return 0;
332         // Do it
333         if(!lua_isnil(L, 2)){
334                 co->m_physics_override_speed = lua_tonumber(L, 2);
335                 co->m_physics_override_sent = false;
336         }
337         if(!lua_isnil(L, 3)){
338                 co->m_physics_override_jump = lua_tonumber(L, 3);
339                 co->m_physics_override_sent = false;
340         }
341         if(!lua_isnil(L, 4)){
342                 co->m_physics_override_gravity = lua_tonumber(L, 4);
343                 co->m_physics_override_sent = false;
344         }
345         return 0;
346 }
347
348 // set_animation(self, frame_range, frame_speed, frame_blend)
349 int ObjectRef::l_set_animation(lua_State *L)
350 {
351         ObjectRef *ref = checkobject(L, 1);
352         ServerActiveObject *co = getobject(ref);
353         if(co == NULL) return 0;
354         // Do it
355         v2f frames = v2f(1, 1);
356         if(!lua_isnil(L, 2))
357                 frames = read_v2f(L, 2);
358         float frame_speed = 15;
359         if(!lua_isnil(L, 3))
360                 frame_speed = lua_tonumber(L, 3);
361         float frame_blend = 0;
362         if(!lua_isnil(L, 4))
363                 frame_blend = lua_tonumber(L, 4);
364         co->setAnimation(frames, frame_speed, frame_blend);
365         return 0;
366 }
367
368 // set_bone_position(self, std::string bone, v3f position, v3f rotation)
369 int ObjectRef::l_set_bone_position(lua_State *L)
370 {
371         ObjectRef *ref = checkobject(L, 1);
372         ServerActiveObject *co = getobject(ref);
373         if(co == NULL) return 0;
374         // Do it
375         std::string bone = "";
376         if(!lua_isnil(L, 2))
377                 bone = lua_tostring(L, 2);
378         v3f position = v3f(0, 0, 0);
379         if(!lua_isnil(L, 3))
380                 position = read_v3f(L, 3);
381         v3f rotation = v3f(0, 0, 0);
382         if(!lua_isnil(L, 4))
383                 rotation = read_v3f(L, 4);
384         co->setBonePosition(bone, position, rotation);
385         return 0;
386 }
387
388 // set_attach(self, parent, bone, position, rotation)
389 int ObjectRef::l_set_attach(lua_State *L)
390 {
391         ObjectRef *ref = checkobject(L, 1);
392         ObjectRef *parent_ref = checkobject(L, 2);
393         ServerActiveObject *co = getobject(ref);
394         ServerActiveObject *parent = getobject(parent_ref);
395         if(co == NULL) return 0;
396         if(parent == NULL) return 0;
397         // Do it
398         std::string bone = "";
399         if(!lua_isnil(L, 3))
400                 bone = lua_tostring(L, 3);
401         v3f position = v3f(0, 0, 0);
402         if(!lua_isnil(L, 4))
403                 position = read_v3f(L, 4);
404         v3f rotation = v3f(0, 0, 0);
405         if(!lua_isnil(L, 5))
406                 rotation = read_v3f(L, 5);
407         co->setAttachment(parent->getId(), bone, position, rotation);
408         return 0;
409 }
410
411 // set_detach(self)
412 int ObjectRef::l_set_detach(lua_State *L)
413 {
414         ObjectRef *ref = checkobject(L, 1);
415         ServerActiveObject *co = getobject(ref);
416         if(co == NULL) return 0;
417         // Do it
418         co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0));
419         return 0;
420 }
421
422 // set_properties(self, properties)
423 int ObjectRef::l_set_properties(lua_State *L)
424 {
425         ObjectRef *ref = checkobject(L, 1);
426         ServerActiveObject *co = getobject(ref);
427         if(co == NULL) return 0;
428         ObjectProperties *prop = co->accessObjectProperties();
429         if(!prop)
430                 return 0;
431         read_object_properties(L, 2, prop);
432         co->notifyObjectPropertiesModified();
433         return 0;
434 }
435
436 /* LuaEntitySAO-only */
437
438 // setvelocity(self, {x=num, y=num, z=num})
439 int ObjectRef::l_setvelocity(lua_State *L)
440 {
441         ObjectRef *ref = checkobject(L, 1);
442         LuaEntitySAO *co = getluaobject(ref);
443         if(co == NULL) return 0;
444         v3f pos = checkFloatPos(L, 2);
445         // Do it
446         co->setVelocity(pos);
447         return 0;
448 }
449
450 // getvelocity(self)
451 int ObjectRef::l_getvelocity(lua_State *L)
452 {
453         ObjectRef *ref = checkobject(L, 1);
454         LuaEntitySAO *co = getluaobject(ref);
455         if(co == NULL) return 0;
456         // Do it
457         v3f v = co->getVelocity();
458         pushFloatPos(L, v);
459         return 1;
460 }
461
462 // setacceleration(self, {x=num, y=num, z=num})
463 int ObjectRef::l_setacceleration(lua_State *L)
464 {
465         ObjectRef *ref = checkobject(L, 1);
466         LuaEntitySAO *co = getluaobject(ref);
467         if(co == NULL) return 0;
468         // pos
469         v3f pos = checkFloatPos(L, 2);
470         // Do it
471         co->setAcceleration(pos);
472         return 0;
473 }
474
475 // getacceleration(self)
476 int ObjectRef::l_getacceleration(lua_State *L)
477 {
478         ObjectRef *ref = checkobject(L, 1);
479         LuaEntitySAO *co = getluaobject(ref);
480         if(co == NULL) return 0;
481         // Do it
482         v3f v = co->getAcceleration();
483         pushFloatPos(L, v);
484         return 1;
485 }
486
487 // setyaw(self, radians)
488 int ObjectRef::l_setyaw(lua_State *L)
489 {
490         ObjectRef *ref = checkobject(L, 1);
491         LuaEntitySAO *co = getluaobject(ref);
492         if(co == NULL) return 0;
493         float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
494         // Do it
495         co->setYaw(yaw);
496         return 0;
497 }
498
499 // getyaw(self)
500 int ObjectRef::l_getyaw(lua_State *L)
501 {
502         ObjectRef *ref = checkobject(L, 1);
503         LuaEntitySAO *co = getluaobject(ref);
504         if(co == NULL) return 0;
505         // Do it
506         float yaw = co->getYaw() * core::DEGTORAD;
507         lua_pushnumber(L, yaw);
508         return 1;
509 }
510
511 // settexturemod(self, mod)
512 int ObjectRef::l_settexturemod(lua_State *L)
513 {
514         ObjectRef *ref = checkobject(L, 1);
515         LuaEntitySAO *co = getluaobject(ref);
516         if(co == NULL) return 0;
517         // Do it
518         std::string mod = luaL_checkstring(L, 2);
519         co->setTextureMod(mod);
520         return 0;
521 }
522
523 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
524 //           select_horiz_by_yawpitch=false)
525 int ObjectRef::l_setsprite(lua_State *L)
526 {
527         ObjectRef *ref = checkobject(L, 1);
528         LuaEntitySAO *co = getluaobject(ref);
529         if(co == NULL) return 0;
530         // Do it
531         v2s16 p(0,0);
532         if(!lua_isnil(L, 2))
533                 p = read_v2s16(L, 2);
534         int num_frames = 1;
535         if(!lua_isnil(L, 3))
536                 num_frames = lua_tonumber(L, 3);
537         float framelength = 0.2;
538         if(!lua_isnil(L, 4))
539                 framelength = lua_tonumber(L, 4);
540         bool select_horiz_by_yawpitch = false;
541         if(!lua_isnil(L, 5))
542                 select_horiz_by_yawpitch = lua_toboolean(L, 5);
543         co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
544         return 0;
545 }
546
547 // DEPRECATED
548 // get_entity_name(self)
549 int ObjectRef::l_get_entity_name(lua_State *L)
550 {
551         ObjectRef *ref = checkobject(L, 1);
552         LuaEntitySAO *co = getluaobject(ref);
553         if(co == NULL) return 0;
554         // Do it
555         std::string name = co->getName();
556         lua_pushstring(L, name.c_str());
557         return 1;
558 }
559
560 // get_luaentity(self)
561 int ObjectRef::l_get_luaentity(lua_State *L)
562 {
563         ObjectRef *ref = checkobject(L, 1);
564         LuaEntitySAO *co = getluaobject(ref);
565         if(co == NULL) return 0;
566         // Do it
567         luaentity_get(L, co->getId());
568         return 1;
569 }
570
571 /* Player-only */
572
573 // is_player(self)
574 int ObjectRef::l_is_player(lua_State *L)
575 {
576         ObjectRef *ref = checkobject(L, 1);
577         Player *player = getplayer(ref);
578         lua_pushboolean(L, (player != NULL));
579         return 1;
580 }
581
582 // get_player_name(self)
583 int ObjectRef::l_get_player_name(lua_State *L)
584 {
585         ObjectRef *ref = checkobject(L, 1);
586         Player *player = getplayer(ref);
587         if(player == NULL){
588                 lua_pushlstring(L, "", 0);
589                 return 1;
590         }
591         // Do it
592         lua_pushstring(L, player->getName());
593         return 1;
594 }
595
596 // get_look_dir(self)
597 int ObjectRef::l_get_look_dir(lua_State *L)
598 {
599         ObjectRef *ref = checkobject(L, 1);
600         Player *player = getplayer(ref);
601         if(player == NULL) return 0;
602         // Do it
603         float pitch = player->getRadPitch();
604         float yaw = player->getRadYaw();
605         v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw));
606         push_v3f(L, v);
607         return 1;
608 }
609
610 // get_look_pitch(self)
611 int ObjectRef::l_get_look_pitch(lua_State *L)
612 {
613         ObjectRef *ref = checkobject(L, 1);
614         Player *player = getplayer(ref);
615         if(player == NULL) return 0;
616         // Do it
617         lua_pushnumber(L, player->getRadPitch());
618         return 1;
619 }
620
621 // get_look_yaw(self)
622 int ObjectRef::l_get_look_yaw(lua_State *L)
623 {
624         ObjectRef *ref = checkobject(L, 1);
625         Player *player = getplayer(ref);
626         if(player == NULL) return 0;
627         // Do it
628         lua_pushnumber(L, player->getRadYaw());
629         return 1;
630 }
631
632 // set_look_pitch(self, radians)
633 int ObjectRef::l_set_look_pitch(lua_State *L)
634 {
635         ObjectRef *ref = checkobject(L, 1);
636         PlayerSAO* co = getplayersao(ref);
637         if(co == NULL) return 0;
638         float pitch = luaL_checknumber(L, 2) * core::RADTODEG;
639         // Do it
640         co->setPitch(pitch);
641         return 1;
642 }
643
644 // set_look_yaw(self, radians)
645 int ObjectRef::l_set_look_yaw(lua_State *L)
646 {
647         ObjectRef *ref = checkobject(L, 1);
648         PlayerSAO* co = getplayersao(ref);
649         if(co == NULL) return 0;
650         float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
651         // Do it
652         co->setYaw(yaw);
653         return 1;
654 }
655
656 // set_inventory_formspec(self, formspec)
657 int ObjectRef::l_set_inventory_formspec(lua_State *L)
658 {
659         ObjectRef *ref = checkobject(L, 1);
660         Player *player = getplayer(ref);
661         if(player == NULL) return 0;
662         std::string formspec = luaL_checkstring(L, 2);
663
664         player->inventory_formspec = formspec;
665         get_server(L)->reportInventoryFormspecModified(player->getName());
666         lua_pushboolean(L, true);
667         return 1;
668 }
669
670 // get_inventory_formspec(self) -> formspec
671 int ObjectRef::l_get_inventory_formspec(lua_State *L)
672 {
673         ObjectRef *ref = checkobject(L, 1);
674         Player *player = getplayer(ref);
675         if(player == NULL) return 0;
676
677         std::string formspec = player->inventory_formspec;
678         lua_pushlstring(L, formspec.c_str(), formspec.size());
679         return 1;
680 }
681
682 // get_player_control(self)
683 int ObjectRef::l_get_player_control(lua_State *L)
684 {
685         ObjectRef *ref = checkobject(L, 1);
686         Player *player = getplayer(ref);
687         if(player == NULL){
688                 lua_pushlstring(L, "", 0);
689                 return 1;
690         }
691         // Do it
692         PlayerControl control = player->getPlayerControl();
693         lua_newtable(L);
694         lua_pushboolean(L, control.up);
695         lua_setfield(L, -2, "up");
696         lua_pushboolean(L, control.down);
697         lua_setfield(L, -2, "down");
698         lua_pushboolean(L, control.left);
699         lua_setfield(L, -2, "left");
700         lua_pushboolean(L, control.right);
701         lua_setfield(L, -2, "right");
702         lua_pushboolean(L, control.jump);
703         lua_setfield(L, -2, "jump");
704         lua_pushboolean(L, control.aux1);
705         lua_setfield(L, -2, "aux1");
706         lua_pushboolean(L, control.sneak);
707         lua_setfield(L, -2, "sneak");
708         lua_pushboolean(L, control.LMB);
709         lua_setfield(L, -2, "LMB");
710         lua_pushboolean(L, control.RMB);
711         lua_setfield(L, -2, "RMB");
712         return 1;
713 }
714
715 // get_player_control_bits(self)
716 int ObjectRef::l_get_player_control_bits(lua_State *L)
717 {
718         ObjectRef *ref = checkobject(L, 1);
719         Player *player = getplayer(ref);
720         if(player == NULL){
721                 lua_pushlstring(L, "", 0);
722                 return 1;
723         }
724         // Do it
725         lua_pushnumber(L, player->keyPressed);
726         return 1;
727 }
728
729 // hud_add(self, form)
730 int ObjectRef::l_hud_add(lua_State *L)
731 {
732         ObjectRef *ref = checkobject(L, 1);
733         Player *player = getplayer(ref);
734         if (player == NULL)
735                 return 0;
736
737         HudElement *elem = new HudElement;
738         
739         elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type",
740                                                                 es_HudElementType, HUD_ELEM_TEXT);
741         
742         lua_getfield(L, 2, "position");
743         elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
744         lua_pop(L, 1);
745         
746         lua_getfield(L, 2, "scale");
747         elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
748         lua_pop(L, 1);
749         
750         elem->name   = getstringfield_default(L, 2, "name", "");
751         elem->text   = getstringfield_default(L, 2, "text", "");
752         elem->number = getintfield_default(L, 2, "number", 0);
753         elem->item   = getintfield_default(L, 2, "item", 0);
754         elem->dir    = getintfield_default(L, 2, "direction", 0);
755
756         lua_getfield(L, 2, "alignment");
757         elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
758         lua_pop(L, 1);
759
760         lua_getfield(L, 2, "offset");
761         elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
762         lua_pop(L, 1);
763
764         u32 id = get_server(L)->hudAdd(player, elem);
765         if (id == (u32)-1) {
766                 delete elem;
767                 return 0;
768         }
769
770         lua_pushnumber(L, id);
771         return 1;
772 }
773
774 // hud_remove(self, id)
775 int ObjectRef::l_hud_remove(lua_State *L)
776 {
777         ObjectRef *ref = checkobject(L, 1);
778         Player *player = getplayer(ref);
779         if (player == NULL)
780                 return 0;
781
782         u32 id = -1;
783         if (!lua_isnil(L, 2))
784                 id = lua_tonumber(L, 2);
785         
786         if (!get_server(L)->hudRemove(player, id))
787                 return 0;
788
789         lua_pushboolean(L, true);
790         return 1;
791 }
792
793 // hud_change(self, id, stat, data)
794 int ObjectRef::l_hud_change(lua_State *L)
795 {
796         ObjectRef *ref = checkobject(L, 1);
797         Player *player = getplayer(ref);
798         if (player == NULL)
799                 return 0;
800
801         u32 id = !lua_isnil(L, 2) ? lua_tonumber(L, 2) : -1;
802         if (id >= player->hud.size())
803                 return 0;
804                 
805         HudElementStat stat = HUD_STAT_NUMBER;
806         if (!lua_isnil(L, 3)) {
807                 int statint;
808                 std::string statstr = lua_tostring(L, 3);
809                 stat = string_to_enum(es_HudElementStat, statint, statstr) ?
810                                 (HudElementStat)statint : HUD_STAT_NUMBER;
811         }
812         
813         void *value = NULL;
814         HudElement *e = player->hud[id];
815         if (!e)
816                 return 0;
817         
818         switch (stat) {
819                 case HUD_STAT_POS:
820                         e->pos = read_v2f(L, 4);
821                         value = &e->pos;
822                         break;
823                 case HUD_STAT_NAME:
824                         e->name = lua_tostring(L, 4);
825                         value = &e->name;
826                         break;
827                 case HUD_STAT_SCALE:
828                         e->scale = read_v2f(L, 4);
829                         value = &e->scale;
830                         break;
831                 case HUD_STAT_TEXT:
832                         e->text = lua_tostring(L, 4);
833                         value = &e->text;
834                         break;
835                 case HUD_STAT_NUMBER:
836                         e->number = lua_tonumber(L, 4);
837                         value = &e->number;
838                         break;
839                 case HUD_STAT_ITEM:
840                         e->item = lua_tonumber(L, 4);
841                         value = &e->item;
842                         break;
843                 case HUD_STAT_DIR:
844                         e->dir = lua_tonumber(L, 4);
845                         value = &e->dir;
846                 case HUD_STAT_ALIGN:
847                         e->align = read_v2f(L, 4);
848                         value = &e->align;
849                 case HUD_STAT_OFFSET:
850                         e->offset = read_v2f(L, 4);
851                         value = &e->offset;
852         }
853
854         get_server(L)->hudChange(player, id, stat, value);
855
856         lua_pushboolean(L, true);
857         return 1;
858 }
859
860 // hud_get(self, id)
861 int ObjectRef::l_hud_get(lua_State *L)
862 {
863         ObjectRef *ref = checkobject(L, 1);
864         Player *player = getplayer(ref);
865         if (player == NULL)
866                 return 0;
867
868         u32 id = lua_tonumber(L, -1);
869         if (id >= player->hud.size())
870                 return 0;
871         
872         HudElement *e = player->hud[id];
873         if (!e)
874                 return 0;
875         
876         lua_newtable(L);
877         
878         lua_pushstring(L, es_HudElementType[(u8)e->type].str);
879         lua_setfield(L, -2, "type");
880         
881         push_v2f(L, e->pos);
882         lua_setfield(L, -2, "position");
883         
884         lua_pushstring(L, e->name.c_str());
885         lua_setfield(L, -2, "name");
886         
887         push_v2f(L, e->scale);
888         lua_setfield(L, -2, "scale");
889         
890         lua_pushstring(L, e->text.c_str());
891         lua_setfield(L, -2, "text");
892         
893         lua_pushnumber(L, e->number);
894         lua_setfield(L, -2, "number");
895         
896         lua_pushnumber(L, e->item);
897         lua_setfield(L, -2, "item");
898         
899         lua_pushnumber(L, e->dir);
900         lua_setfield(L, -2, "dir");
901
902         return 1;
903 }
904
905 ObjectRef::ObjectRef(ServerActiveObject *object):
906         m_object(object)
907 {
908         //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
909 }
910
911 ObjectRef::~ObjectRef()
912 {
913         /*if(m_object)
914                 infostream<<"ObjectRef destructing for id="
915                                 <<m_object->getId()<<std::endl;
916         else
917                 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
918 }
919
920 // Creates an ObjectRef and leaves it on top of stack
921 // Not callable from Lua; all references are created on the C side.
922 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
923 {
924         ObjectRef *o = new ObjectRef(object);
925         //infostream<<"ObjectRef::create: o="<<o<<std::endl;
926         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
927         luaL_getmetatable(L, className);
928         lua_setmetatable(L, -2);
929 }
930
931 void ObjectRef::set_null(lua_State *L)
932 {
933         ObjectRef *o = checkobject(L, -1);
934         o->m_object = NULL;
935 }
936
937 void ObjectRef::Register(lua_State *L)
938 {
939         lua_newtable(L);
940         int methodtable = lua_gettop(L);
941         luaL_newmetatable(L, className);
942         int metatable = lua_gettop(L);
943
944         lua_pushliteral(L, "__metatable");
945         lua_pushvalue(L, methodtable);
946         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
947
948         lua_pushliteral(L, "__index");
949         lua_pushvalue(L, methodtable);
950         lua_settable(L, metatable);
951
952         lua_pushliteral(L, "__gc");
953         lua_pushcfunction(L, gc_object);
954         lua_settable(L, metatable);
955
956         lua_pop(L, 1);  // drop metatable
957
958         luaL_openlib(L, 0, methods, 0);  // fill methodtable
959         lua_pop(L, 1);  // drop methodtable
960
961         // Cannot be created from Lua
962         //lua_register(L, className, create_object);
963 }
964
965 const char ObjectRef::className[] = "ObjectRef";
966 const luaL_reg ObjectRef::methods[] = {
967         // ServerActiveObject
968         luamethod(ObjectRef, remove),
969         luamethod(ObjectRef, getpos),
970         luamethod(ObjectRef, setpos),
971         luamethod(ObjectRef, moveto),
972         luamethod(ObjectRef, punch),
973         luamethod(ObjectRef, right_click),
974         luamethod(ObjectRef, set_hp),
975         luamethod(ObjectRef, get_hp),
976         luamethod(ObjectRef, get_inventory),
977         luamethod(ObjectRef, get_wield_list),
978         luamethod(ObjectRef, get_wield_index),
979         luamethod(ObjectRef, get_wielded_item),
980         luamethod(ObjectRef, set_wielded_item),
981         luamethod(ObjectRef, set_armor_groups),
982         luamethod(ObjectRef, set_physics_override),
983         luamethod(ObjectRef, set_animation),
984         luamethod(ObjectRef, set_bone_position),
985         luamethod(ObjectRef, set_attach),
986         luamethod(ObjectRef, set_detach),
987         luamethod(ObjectRef, set_properties),
988         // LuaEntitySAO-only
989         luamethod(ObjectRef, setvelocity),
990         luamethod(ObjectRef, getvelocity),
991         luamethod(ObjectRef, setacceleration),
992         luamethod(ObjectRef, getacceleration),
993         luamethod(ObjectRef, setyaw),
994         luamethod(ObjectRef, getyaw),
995         luamethod(ObjectRef, settexturemod),
996         luamethod(ObjectRef, setsprite),
997         luamethod(ObjectRef, get_entity_name),
998         luamethod(ObjectRef, get_luaentity),
999         // Player-only
1000         luamethod(ObjectRef, is_player),
1001         luamethod(ObjectRef, get_player_name),
1002         luamethod(ObjectRef, get_look_dir),
1003         luamethod(ObjectRef, get_look_pitch),
1004         luamethod(ObjectRef, get_look_yaw),
1005         luamethod(ObjectRef, set_look_yaw),
1006         luamethod(ObjectRef, set_look_pitch),
1007         luamethod(ObjectRef, set_inventory_formspec),
1008         luamethod(ObjectRef, get_inventory_formspec),
1009         luamethod(ObjectRef, get_player_control),
1010         luamethod(ObjectRef, get_player_control_bits),
1011         luamethod(ObjectRef, hud_add),
1012         luamethod(ObjectRef, hud_remove),
1013         luamethod(ObjectRef, hud_change),
1014         luamethod(ObjectRef, hud_get),
1015         //luamethod(ObjectRef, hud_lock_next_bar),
1016         //luamethod(ObjectRef, hud_unlock_bar),
1017         {0,0}
1018 };
1019
1020 // Creates a new anonymous reference if cobj=NULL or id=0
1021 void objectref_get_or_create(lua_State *L,
1022                 ServerActiveObject *cobj)
1023 {
1024         if(cobj == NULL || cobj->getId() == 0){
1025                 ObjectRef::create(L, cobj);
1026         } else {
1027                 objectref_get(L, cobj->getId());
1028         }
1029 }
1030
1031 void objectref_get(lua_State *L, u16 id)
1032 {
1033         // Get minetest.object_refs[i]
1034         lua_getglobal(L, "minetest");
1035         lua_getfield(L, -1, "object_refs");
1036         luaL_checktype(L, -1, LUA_TTABLE);
1037         lua_pushnumber(L, id);
1038         lua_gettable(L, -2);
1039         lua_remove(L, -2); // object_refs
1040         lua_remove(L, -2); // minetest
1041 }
1042
1043 /*
1044         ObjectProperties
1045 */
1046
1047 void read_object_properties(lua_State *L, int index,
1048                 ObjectProperties *prop)
1049 {
1050         if(index < 0)
1051                 index = lua_gettop(L) + 1 + index;
1052         if(!lua_istable(L, index))
1053                 return;
1054
1055         prop->hp_max = getintfield_default(L, -1, "hp_max", 10);
1056
1057         getboolfield(L, -1, "physical", prop->physical);
1058
1059         getfloatfield(L, -1, "weight", prop->weight);
1060
1061         lua_getfield(L, -1, "collisionbox");
1062         if(lua_istable(L, -1))
1063                 prop->collisionbox = read_aabb3f(L, -1, 1.0);
1064         lua_pop(L, 1);
1065
1066         getstringfield(L, -1, "visual", prop->visual);
1067
1068         getstringfield(L, -1, "mesh", prop->mesh);
1069
1070         lua_getfield(L, -1, "visual_size");
1071         if(lua_istable(L, -1))
1072                 prop->visual_size = read_v2f(L, -1);
1073         lua_pop(L, 1);
1074
1075         lua_getfield(L, -1, "textures");
1076         if(lua_istable(L, -1)){
1077                 prop->textures.clear();
1078                 int table = lua_gettop(L);
1079                 lua_pushnil(L);
1080                 while(lua_next(L, table) != 0){
1081                         // key at index -2 and value at index -1
1082                         if(lua_isstring(L, -1))
1083                                 prop->textures.push_back(lua_tostring(L, -1));
1084                         else
1085                                 prop->textures.push_back("");
1086                         // removes value, keeps key for next iteration
1087                         lua_pop(L, 1);
1088                 }
1089         }
1090         lua_pop(L, 1);
1091
1092         lua_getfield(L, -1, "colors");
1093         if(lua_istable(L, -1)){
1094                 prop->colors.clear();
1095                 int table = lua_gettop(L);
1096                 lua_pushnil(L);
1097                 while(lua_next(L, table) != 0){
1098                         // key at index -2 and value at index -1
1099                         if(lua_isstring(L, -1))
1100                                 prop->colors.push_back(readARGB8(L, -1));
1101                         else
1102                                 prop->colors.push_back(video::SColor(255, 255, 255, 255));
1103                         // removes value, keeps key for next iteration
1104                         lua_pop(L, 1);
1105                 }
1106         }
1107         lua_pop(L, 1);
1108
1109         lua_getfield(L, -1, "spritediv");
1110         if(lua_istable(L, -1))
1111                 prop->spritediv = read_v2s16(L, -1);
1112         lua_pop(L, 1);
1113
1114         lua_getfield(L, -1, "initial_sprite_basepos");
1115         if(lua_istable(L, -1))
1116                 prop->initial_sprite_basepos = read_v2s16(L, -1);
1117         lua_pop(L, 1);
1118
1119         getboolfield(L, -1, "is_visible", prop->is_visible);
1120         getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound);
1121         getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate);
1122 }
1123
1124 /*
1125         object_reference
1126 */
1127
1128 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
1129 {
1130         realitycheck(L);
1131         assert(lua_checkstack(L, 20));
1132         //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
1133         StackUnroller stack_unroller(L);
1134
1135         // Create object on stack
1136         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
1137         int object = lua_gettop(L);
1138
1139         // Get minetest.object_refs table
1140         lua_getglobal(L, "minetest");
1141         lua_getfield(L, -1, "object_refs");
1142         luaL_checktype(L, -1, LUA_TTABLE);
1143         int objectstable = lua_gettop(L);
1144
1145         // object_refs[id] = object
1146         lua_pushnumber(L, cobj->getId()); // Push id
1147         lua_pushvalue(L, object); // Copy object to top of stack
1148         lua_settable(L, objectstable);
1149 }
1150
1151 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
1152 {
1153         realitycheck(L);
1154         assert(lua_checkstack(L, 20));
1155         //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
1156         StackUnroller stack_unroller(L);
1157
1158         // Get minetest.object_refs table
1159         lua_getglobal(L, "minetest");
1160         lua_getfield(L, -1, "object_refs");
1161         luaL_checktype(L, -1, LUA_TTABLE);
1162         int objectstable = lua_gettop(L);
1163
1164         // Get object_refs[id]
1165         lua_pushnumber(L, cobj->getId()); // Push id
1166         lua_gettable(L, objectstable);
1167         // Set object reference to NULL
1168         ObjectRef::set_null(L);
1169         lua_pop(L, 1); // pop object
1170
1171         // Set object_refs[id] = nil
1172         lua_pushnumber(L, cobj->getId()); // Push id
1173         lua_pushnil(L);
1174         lua_settable(L, objectstable);
1175 }