Fix some issues with animations, and allow non-looped animations to be defined
[oweals/minetest.git] / src / script / lua_api / l_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 "lua_api/l_object.h"
21 #include "lua_api/l_internal.h"
22 #include "lua_api/l_inventory.h"
23 #include "lua_api/l_item.h"
24 #include "common/c_converter.h"
25 #include "common/c_content.h"
26 #include "log.h"
27 #include "tool.h"
28 #include "serverobject.h"
29 #include "content_sao.h"
30 #include "server.h"
31 #include "hud.h"
32 #include "scripting_game.h"
33
34 #define GET_ENV_PTR ServerEnvironment* env =                                   \
35                                 dynamic_cast<ServerEnvironment*>(getEnv(L));                   \
36                                 if (env == NULL) return 0
37
38 struct EnumString es_HudElementType[] =
39 {
40         {HUD_ELEM_IMAGE,     "image"},
41         {HUD_ELEM_TEXT,      "text"},
42         {HUD_ELEM_STATBAR,   "statbar"},
43         {HUD_ELEM_INVENTORY, "inventory"},
44         {HUD_ELEM_WAYPOINT,  "waypoint"},
45 {0, NULL},
46 };
47
48 struct EnumString es_HudElementStat[] =
49 {
50         {HUD_STAT_POS,    "position"},
51         {HUD_STAT_POS,    "pos"}, /* Deprecated, only for compatibility's sake */
52         {HUD_STAT_NAME,   "name"},
53         {HUD_STAT_SCALE,  "scale"},
54         {HUD_STAT_TEXT,   "text"},
55         {HUD_STAT_NUMBER, "number"},
56         {HUD_STAT_ITEM,   "item"},
57         {HUD_STAT_DIR,    "direction"},
58         {HUD_STAT_ALIGN,  "alignment"},
59         {HUD_STAT_OFFSET, "offset"},
60         {HUD_STAT_WORLD_POS, "world_pos"},
61         {0, NULL},
62 };
63
64 struct EnumString es_HudBuiltinElement[] =
65 {
66         {HUD_FLAG_HOTBAR_VISIBLE,    "hotbar"},
67         {HUD_FLAG_HEALTHBAR_VISIBLE, "healthbar"},
68         {HUD_FLAG_CROSSHAIR_VISIBLE, "crosshair"},
69         {HUD_FLAG_WIELDITEM_VISIBLE, "wielditem"},
70         {HUD_FLAG_BREATHBAR_VISIBLE, "breathbar"},
71         {0, NULL},
72 };
73
74 /*
75         ObjectRef
76 */
77
78
79 ObjectRef* ObjectRef::checkobject(lua_State *L, int narg)
80 {
81         luaL_checktype(L, narg, LUA_TUSERDATA);
82         void *ud = luaL_checkudata(L, narg, className);
83         if(!ud) luaL_typerror(L, narg, className);
84         return *(ObjectRef**)ud;  // unbox pointer
85 }
86
87 ServerActiveObject* ObjectRef::getobject(ObjectRef *ref)
88 {
89         ServerActiveObject *co = ref->m_object;
90         return co;
91 }
92
93 LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
94 {
95         ServerActiveObject *obj = getobject(ref);
96         if(obj == NULL)
97                 return NULL;
98         if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
99                 return NULL;
100         return (LuaEntitySAO*)obj;
101 }
102
103 PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
104 {
105         ServerActiveObject *obj = getobject(ref);
106         if(obj == NULL)
107                 return NULL;
108         if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
109                 return NULL;
110         return (PlayerSAO*)obj;
111 }
112
113 Player* ObjectRef::getplayer(ObjectRef *ref)
114 {
115         PlayerSAO *playersao = getplayersao(ref);
116         if(playersao == NULL)
117                 return NULL;
118         return playersao->getPlayer();
119 }
120
121 // Exported functions
122
123 // garbage collector
124 int ObjectRef::gc_object(lua_State *L) {
125         ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
126         //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
127         delete o;
128         return 0;
129 }
130
131 // remove(self)
132 int ObjectRef::l_remove(lua_State *L)
133 {
134         NO_MAP_LOCK_REQUIRED;
135         ObjectRef *ref = checkobject(L, 1);
136         ServerActiveObject *co = getobject(ref);
137         if(co == NULL) return 0;
138         if(co->getType() == ACTIVEOBJECT_TYPE_PLAYER) return 0;
139         verbosestream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
140         co->m_removed = true;
141         return 0;
142 }
143
144 // getpos(self)
145 // returns: {x=num, y=num, z=num}
146 int ObjectRef::l_getpos(lua_State *L)
147 {
148         NO_MAP_LOCK_REQUIRED;
149         ObjectRef *ref = checkobject(L, 1);
150         ServerActiveObject *co = getobject(ref);
151         if(co == NULL) return 0;
152         v3f pos = co->getBasePosition() / BS;
153         lua_newtable(L);
154         lua_pushnumber(L, pos.X);
155         lua_setfield(L, -2, "x");
156         lua_pushnumber(L, pos.Y);
157         lua_setfield(L, -2, "y");
158         lua_pushnumber(L, pos.Z);
159         lua_setfield(L, -2, "z");
160         return 1;
161 }
162
163 // setpos(self, pos)
164 int ObjectRef::l_setpos(lua_State *L)
165 {
166         NO_MAP_LOCK_REQUIRED;
167         ObjectRef *ref = checkobject(L, 1);
168         //LuaEntitySAO *co = getluaobject(ref);
169         ServerActiveObject *co = getobject(ref);
170         if(co == NULL) return 0;
171         // pos
172         v3f pos = checkFloatPos(L, 2);
173         // Do it
174         co->setPos(pos);
175         return 0;
176 }
177
178 // moveto(self, pos, continuous=false)
179 int ObjectRef::l_moveto(lua_State *L)
180 {
181         NO_MAP_LOCK_REQUIRED;
182         ObjectRef *ref = checkobject(L, 1);
183         //LuaEntitySAO *co = getluaobject(ref);
184         ServerActiveObject *co = getobject(ref);
185         if(co == NULL) return 0;
186         // pos
187         v3f pos = checkFloatPos(L, 2);
188         // continuous
189         bool continuous = lua_toboolean(L, 3);
190         // Do it
191         co->moveTo(pos, continuous);
192         return 0;
193 }
194
195 // punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
196 int ObjectRef::l_punch(lua_State *L)
197 {
198         NO_MAP_LOCK_REQUIRED;
199         ObjectRef *ref = checkobject(L, 1);
200         ObjectRef *puncher_ref = checkobject(L, 2);
201         ServerActiveObject *co = getobject(ref);
202         ServerActiveObject *puncher = getobject(puncher_ref);
203         if(co == NULL) return 0;
204         if(puncher == NULL) return 0;
205         v3f dir;
206         if(lua_type(L, 5) != LUA_TTABLE)
207                 dir = co->getBasePosition() - puncher->getBasePosition();
208         else
209                 dir = read_v3f(L, 5);
210         float time_from_last_punch = 1000000;
211         if(lua_isnumber(L, 3))
212                 time_from_last_punch = lua_tonumber(L, 3);
213         ToolCapabilities toolcap = read_tool_capabilities(L, 4);
214         dir.normalize();
215
216         s16 src_original_hp = co->getHP();
217         s16 dst_origin_hp = puncher->getHP();
218
219         // Do it
220         co->punch(dir, &toolcap, puncher, time_from_last_punch);
221
222         // If the punched is a player, and its HP changed
223         if (src_original_hp != co->getHP() &&
224                         co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
225                 getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)co)->getPeerID(),
226                                 co->getHP() == 0);
227         }
228
229         // If the puncher is a player, and its HP changed
230         if (dst_origin_hp != puncher->getHP() &&
231                         puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
232                 getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)puncher)->getPeerID(),
233                                 puncher->getHP() == 0);
234         }
235         return 0;
236 }
237
238 // right_click(self, clicker); clicker = an another ObjectRef
239 int ObjectRef::l_right_click(lua_State *L)
240 {
241         NO_MAP_LOCK_REQUIRED;
242         ObjectRef *ref = checkobject(L, 1);
243         ObjectRef *ref2 = checkobject(L, 2);
244         ServerActiveObject *co = getobject(ref);
245         ServerActiveObject *co2 = getobject(ref2);
246         if(co == NULL) return 0;
247         if(co2 == NULL) return 0;
248         // Do it
249         co->rightClick(co2);
250         return 0;
251 }
252
253 // set_hp(self, hp)
254 // hp = number of hitpoints (2 * number of hearts)
255 // returns: nil
256 int ObjectRef::l_set_hp(lua_State *L)
257 {
258         NO_MAP_LOCK_REQUIRED;
259         ObjectRef *ref = checkobject(L, 1);
260         luaL_checknumber(L, 2);
261         ServerActiveObject *co = getobject(ref);
262         if(co == NULL) return 0;
263         int hp = lua_tonumber(L, 2);
264         /*infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
265                         <<" hp="<<hp<<std::endl;*/
266         // Do it
267         co->setHP(hp);
268         if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
269                 getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)co)->getPeerID(), co->getHP() == 0);
270         }
271         // Return
272         return 0;
273 }
274
275 // get_hp(self)
276 // returns: number of hitpoints (2 * number of hearts)
277 // 0 if not applicable to this type of object
278 int ObjectRef::l_get_hp(lua_State *L)
279 {
280         NO_MAP_LOCK_REQUIRED;
281         ObjectRef *ref = checkobject(L, 1);
282         ServerActiveObject *co = getobject(ref);
283         if(co == NULL){
284                 // Default hp is 1
285                 lua_pushnumber(L, 1);
286                 return 1;
287         }
288         int hp = co->getHP();
289         /*infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
290                         <<" hp="<<hp<<std::endl;*/
291         // Return
292         lua_pushnumber(L, hp);
293         return 1;
294 }
295
296 // get_inventory(self)
297 int ObjectRef::l_get_inventory(lua_State *L)
298 {
299         NO_MAP_LOCK_REQUIRED;
300         ObjectRef *ref = checkobject(L, 1);
301         ServerActiveObject *co = getobject(ref);
302         if(co == NULL) return 0;
303         // Do it
304         InventoryLocation loc = co->getInventoryLocation();
305         if(getServer(L)->getInventory(loc) != NULL)
306                 InvRef::create(L, loc);
307         else
308                 lua_pushnil(L); // An object may have no inventory (nil)
309         return 1;
310 }
311
312 // get_wield_list(self)
313 int ObjectRef::l_get_wield_list(lua_State *L)
314 {
315         NO_MAP_LOCK_REQUIRED;
316         ObjectRef *ref = checkobject(L, 1);
317         ServerActiveObject *co = getobject(ref);
318         if(co == NULL) return 0;
319         // Do it
320         lua_pushstring(L, co->getWieldList().c_str());
321         return 1;
322 }
323
324 // get_wield_index(self)
325 int ObjectRef::l_get_wield_index(lua_State *L)
326 {
327         NO_MAP_LOCK_REQUIRED;
328         ObjectRef *ref = checkobject(L, 1);
329         ServerActiveObject *co = getobject(ref);
330         if(co == NULL) return 0;
331         // Do it
332         lua_pushinteger(L, co->getWieldIndex() + 1);
333         return 1;
334 }
335
336 // get_wielded_item(self)
337 int ObjectRef::l_get_wielded_item(lua_State *L)
338 {
339         NO_MAP_LOCK_REQUIRED;
340         ObjectRef *ref = checkobject(L, 1);
341         ServerActiveObject *co = getobject(ref);
342         if(co == NULL){
343                 // Empty ItemStack
344                 LuaItemStack::create(L, ItemStack());
345                 return 1;
346         }
347         // Do it
348         LuaItemStack::create(L, co->getWieldedItem());
349         return 1;
350 }
351
352 // set_wielded_item(self, itemstack or itemstring or table or nil)
353 int ObjectRef::l_set_wielded_item(lua_State *L)
354 {
355         NO_MAP_LOCK_REQUIRED;
356         ObjectRef *ref = checkobject(L, 1);
357         ServerActiveObject *co = getobject(ref);
358         if(co == NULL) return 0;
359         // Do it
360         ItemStack item = read_item(L, 2, getServer(L));
361         bool success = co->setWieldedItem(item);
362         if (success && co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
363                 getServer(L)->SendInventory(((PlayerSAO*)co));
364         }
365         lua_pushboolean(L, success);
366         return 1;
367 }
368
369 // set_armor_groups(self, groups)
370 int ObjectRef::l_set_armor_groups(lua_State *L)
371 {
372         NO_MAP_LOCK_REQUIRED;
373         ObjectRef *ref = checkobject(L, 1);
374         ServerActiveObject *co = getobject(ref);
375         if(co == NULL) return 0;
376         // Do it
377         ItemGroupList groups;
378         read_groups(L, 2, groups);
379         co->setArmorGroups(groups);
380         return 0;
381 }
382
383 // get_armor_groups(self)
384 int ObjectRef::l_get_armor_groups(lua_State *L)
385 {
386         NO_MAP_LOCK_REQUIRED;
387         ObjectRef *ref = checkobject(L, 1);
388         ServerActiveObject *co = getobject(ref);
389         if (co == NULL)
390                 return 0;
391         // Do it
392         ItemGroupList groups = co->getArmorGroups();
393         push_groups(L, groups);
394         return 1;
395 }
396
397 // set_physics_override(self, physics_override_speed, physics_override_jump,
398 //                      physics_override_gravity, sneak, sneak_glitch)
399 int ObjectRef::l_set_physics_override(lua_State *L)
400 {
401         ObjectRef *ref = checkobject(L, 1);
402         PlayerSAO *co = (PlayerSAO *) getobject(ref);
403         if(co == NULL) return 0;
404         // Do it
405         if (lua_istable(L, 2)) {
406                 co->m_physics_override_speed = getfloatfield_default(L, 2, "speed", co->m_physics_override_speed);
407                 co->m_physics_override_jump = getfloatfield_default(L, 2, "jump", co->m_physics_override_jump);
408                 co->m_physics_override_gravity = getfloatfield_default(L, 2, "gravity", co->m_physics_override_gravity);
409                 co->m_physics_override_sneak = getboolfield_default(L, 2, "sneak", co->m_physics_override_sneak);
410                 co->m_physics_override_sneak_glitch = getboolfield_default(L, 2, "sneak_glitch", co->m_physics_override_sneak_glitch);
411                 co->m_physics_override_sent = false;
412         } else {
413                 // old, non-table format
414                 if(!lua_isnil(L, 2)){
415                         co->m_physics_override_speed = lua_tonumber(L, 2);
416                         co->m_physics_override_sent = false;
417                 }
418                 if(!lua_isnil(L, 3)){
419                         co->m_physics_override_jump = lua_tonumber(L, 3);
420                         co->m_physics_override_sent = false;
421                 }
422                 if(!lua_isnil(L, 4)){
423                         co->m_physics_override_gravity = lua_tonumber(L, 4);
424                         co->m_physics_override_sent = false;
425                 }
426         }
427         return 0;
428 }
429
430 // get_physics_override(self)
431 int ObjectRef::l_get_physics_override(lua_State *L)
432 {
433         ObjectRef *ref = checkobject(L, 1);
434         PlayerSAO *co = (PlayerSAO *)getobject(ref);
435         if (co == NULL)
436                 return 0;
437         // Do it
438         lua_newtable(L);
439         lua_pushnumber(L, co->m_physics_override_speed);
440         lua_setfield(L, -2, "speed");
441         lua_pushnumber(L, co->m_physics_override_jump);
442         lua_setfield(L, -2, "jump");
443         lua_pushnumber(L, co->m_physics_override_gravity);
444         lua_setfield(L, -2, "gravity");
445         lua_pushboolean(L, co->m_physics_override_sneak);
446         lua_setfield(L, -2, "sneak");
447         lua_pushboolean(L, co->m_physics_override_sneak_glitch);
448         lua_setfield(L, -2, "sneak_glitch");
449         return 1;
450 }
451
452 // set_animation(self, frame_range, frame_speed, frame_blend, frame_loop)
453 int ObjectRef::l_set_animation(lua_State *L)
454 {
455         NO_MAP_LOCK_REQUIRED;
456         ObjectRef *ref = checkobject(L, 1);
457         ServerActiveObject *co = getobject(ref);
458         if(co == NULL) return 0;
459         // Do it
460         v2f frames = v2f(1, 1);
461         if(!lua_isnil(L, 2))
462                 frames = read_v2f(L, 2);
463         float frame_speed = 15;
464         if(!lua_isnil(L, 3))
465                 frame_speed = lua_tonumber(L, 3);
466         float frame_blend = 0;
467         if(!lua_isnil(L, 4))
468                 frame_blend = lua_tonumber(L, 4);
469         bool frame_loop = true;
470         if(lua_isboolean(L, 5))
471                 frame_loop = lua_toboolean(L, 5);
472         co->setAnimation(frames, frame_speed, frame_blend, frame_loop);
473         return 0;
474 }
475
476 // get_animation(self)
477 int ObjectRef::l_get_animation(lua_State *L)
478 {
479         NO_MAP_LOCK_REQUIRED;
480         ObjectRef *ref = checkobject(L, 1);
481         ServerActiveObject *co = getobject(ref);
482         if (co == NULL)
483                 return 0;
484         // Do it
485         v2f frames = v2f(1,1);
486         float frame_speed = 15;
487         float frame_blend = 0;
488         bool frame_loop = true;
489         co->getAnimation(&frames, &frame_speed, &frame_blend, &frame_loop);
490
491         push_v2f(L, frames);
492         lua_pushnumber(L, frame_speed);
493         lua_pushnumber(L, frame_blend);
494         lua_pushboolean(L, frame_loop);
495         return 4;
496 }
497
498 // set_local_animation(self, {stand/idle}, {walk}, {dig}, {walk+dig}, frame_speed)
499 int ObjectRef::l_set_local_animation(lua_State *L)
500 {
501         //NO_MAP_LOCK_REQUIRED;
502         ObjectRef *ref = checkobject(L, 1);
503         Player *player = getplayer(ref);
504         if (player == NULL)
505                 return 0;
506         // Do it
507         v2s32 frames[4];
508         for (int i=0;i<4;i++) {
509                 if(!lua_isnil(L, 2+1))
510                         frames[i] = read_v2s32(L, 2+i);
511         }
512         float frame_speed = 30;
513         if(!lua_isnil(L, 6))
514                 frame_speed = lua_tonumber(L, 6);
515
516         if (!getServer(L)->setLocalPlayerAnimations(player, frames, frame_speed))
517                 return 0;
518
519         lua_pushboolean(L, true);
520         return 0;
521 }
522
523 // get_local_animation(self)
524 int ObjectRef::l_get_local_animation(lua_State *L)
525 {
526         //NO_MAP_LOCK_REQUIRED
527         ObjectRef *ref = checkobject(L, 1);
528         Player *player = getplayer(ref);
529         if (player == NULL)
530                 return 0;
531
532         v2s32 frames[4];
533         float frame_speed;
534         player->getLocalAnimations(frames, &frame_speed);
535
536         for (int i = 0; i < 4; i++) {
537                 push_v2s32(L, frames[i]);
538         }
539
540         lua_pushnumber(L, frame_speed);
541         return 5;
542 }
543
544 // set_eye_offset(self, v3f first pv, v3f third pv)
545 int ObjectRef::l_set_eye_offset(lua_State *L)
546 {
547         //NO_MAP_LOCK_REQUIRED;
548         ObjectRef *ref = checkobject(L, 1);
549         Player *player = getplayer(ref);
550         if (player == NULL)
551                 return 0;
552         // Do it
553         v3f offset_first = v3f(0, 0, 0);
554         v3f offset_third = v3f(0, 0, 0);
555
556         if(!lua_isnil(L, 2))
557                 offset_first = read_v3f(L, 2);
558         if(!lua_isnil(L, 3))
559                 offset_third = read_v3f(L, 3);
560
561         // Prevent abuse of offset values (keep player always visible)
562         offset_third.X = rangelim(offset_third.X,-10,10);
563         offset_third.Z = rangelim(offset_third.Z,-5,5);
564         /* TODO: if possible: improve the camera colision detetion to allow Y <= -1.5) */
565         offset_third.Y = rangelim(offset_third.Y,-10,15); //1.5*BS
566
567         if (!getServer(L)->setPlayerEyeOffset(player, offset_first, offset_third))
568                 return 0;
569
570         lua_pushboolean(L, true);
571         return 0;
572 }
573
574 // get_eye_offset(self)
575 int ObjectRef::l_get_eye_offset(lua_State *L)
576 {
577         //NO_MAP_LOCK_REQUIRED;
578         ObjectRef *ref = checkobject(L, 1);
579         Player *player = getplayer(ref);
580         if (player == NULL)
581                 return 0;
582         // Do it
583         push_v3f(L, player->eye_offset_first);
584         push_v3f(L, player->eye_offset_third);
585         return 2;
586 }
587
588 // set_bone_position(self, std::string bone, v3f position, v3f rotation)
589 int ObjectRef::l_set_bone_position(lua_State *L)
590 {
591         NO_MAP_LOCK_REQUIRED;
592         ObjectRef *ref = checkobject(L, 1);
593         ServerActiveObject *co = getobject(ref);
594         if(co == NULL) return 0;
595         // Do it
596         std::string bone = "";
597         if(!lua_isnil(L, 2))
598                 bone = lua_tostring(L, 2);
599         v3f position = v3f(0, 0, 0);
600         if(!lua_isnil(L, 3))
601                 position = read_v3f(L, 3);
602         v3f rotation = v3f(0, 0, 0);
603         if(!lua_isnil(L, 4))
604                 rotation = read_v3f(L, 4);
605         co->setBonePosition(bone, position, rotation);
606         return 0;
607 }
608
609 // get_bone_position(self, bone)
610 int ObjectRef::l_get_bone_position(lua_State *L)
611 {
612         NO_MAP_LOCK_REQUIRED;
613         ObjectRef *ref = checkobject(L, 1);
614         ServerActiveObject *co = getobject(ref);
615         if (co == NULL)
616                 return 0;
617         // Do it
618         std::string bone = "";
619         if(!lua_isnil(L, 2))
620                 bone = lua_tostring(L, 2);
621
622         v3f position = v3f(0, 0, 0);
623         v3f rotation = v3f(0, 0, 0);
624         co->getBonePosition(bone, &position, &rotation);
625
626         push_v3f(L, position);
627         push_v3f(L, rotation);
628         return 2;
629 }
630
631 // set_attach(self, parent, bone, position, rotation)
632 int ObjectRef::l_set_attach(lua_State *L)
633 {
634         NO_MAP_LOCK_REQUIRED;
635         ObjectRef *ref = checkobject(L, 1);
636         ObjectRef *parent_ref = checkobject(L, 2);
637         ServerActiveObject *co = getobject(ref);
638         ServerActiveObject *parent = getobject(parent_ref);
639         if(co == NULL) return 0;
640         if(parent == NULL) return 0;
641         // Do it
642         std::string bone = "";
643         if(!lua_isnil(L, 3))
644                 bone = lua_tostring(L, 3);
645         v3f position = v3f(0, 0, 0);
646         if(!lua_isnil(L, 4))
647                 position = read_v3f(L, 4);
648         v3f rotation = v3f(0, 0, 0);
649         if(!lua_isnil(L, 5))
650                 rotation = read_v3f(L, 5);
651         co->setAttachment(parent->getId(), bone, position, rotation);
652         return 0;
653 }
654
655 // get_attach(self)
656 int ObjectRef::l_get_attach(lua_State *L)
657 {
658         NO_MAP_LOCK_REQUIRED;
659         GET_ENV_PTR;
660
661         ObjectRef *ref = checkobject(L, 1);
662         ServerActiveObject *co = getobject(ref);
663         if (co == NULL)
664                 return 0;
665
666         // Do it
667         int parent_id = 0;
668         std::string bone = "";
669         v3f position = v3f(0, 0, 0);
670         v3f rotation = v3f(0, 0, 0);
671         co->getAttachment(&parent_id, &bone, &position, &rotation);
672         if (!parent_id)
673                 return 0;
674         ServerActiveObject *parent = env->getActiveObject(parent_id);
675
676         getScriptApiBase(L)->objectrefGetOrCreate(L, parent);
677         lua_pushlstring(L, bone.c_str(), bone.size());
678         push_v3f(L, position);
679         push_v3f(L, rotation);
680         return 4;
681 }
682
683 // set_detach(self)
684 int ObjectRef::l_set_detach(lua_State *L)
685 {
686         NO_MAP_LOCK_REQUIRED;
687         ObjectRef *ref = checkobject(L, 1);
688         ServerActiveObject *co = getobject(ref);
689         if(co == NULL) return 0;
690         // Do it
691         co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0));
692         return 0;
693 }
694
695 // set_properties(self, properties)
696 int ObjectRef::l_set_properties(lua_State *L)
697 {
698         NO_MAP_LOCK_REQUIRED;
699         ObjectRef *ref = checkobject(L, 1);
700         ServerActiveObject *co = getobject(ref);
701         if(co == NULL) return 0;
702         ObjectProperties *prop = co->accessObjectProperties();
703         if(!prop)
704                 return 0;
705         read_object_properties(L, 2, prop);
706         co->notifyObjectPropertiesModified();
707         return 0;
708 }
709
710 // get_properties(self)
711 int ObjectRef::l_get_properties(lua_State *L)
712 {
713         NO_MAP_LOCK_REQUIRED;
714         ObjectRef *ref = checkobject(L, 1);
715         ServerActiveObject *co = getobject(ref);
716         if (co == NULL)
717                 return 0;
718         ObjectProperties *prop = co->accessObjectProperties();
719         if (!prop)
720                 return 0;
721         push_object_properties(L, prop);
722         return 1;
723 }
724
725 // is_player(self)
726 int ObjectRef::l_is_player(lua_State *L)
727 {
728         NO_MAP_LOCK_REQUIRED;
729         ObjectRef *ref = checkobject(L, 1);
730         Player *player = getplayer(ref);
731         lua_pushboolean(L, (player != NULL));
732         return 1;
733 }
734
735 /* LuaEntitySAO-only */
736
737 // setvelocity(self, {x=num, y=num, z=num})
738 int ObjectRef::l_setvelocity(lua_State *L)
739 {
740         NO_MAP_LOCK_REQUIRED;
741         ObjectRef *ref = checkobject(L, 1);
742         LuaEntitySAO *co = getluaobject(ref);
743         if(co == NULL) return 0;
744         v3f pos = checkFloatPos(L, 2);
745         // Do it
746         co->setVelocity(pos);
747         return 0;
748 }
749
750 // getvelocity(self)
751 int ObjectRef::l_getvelocity(lua_State *L)
752 {
753         NO_MAP_LOCK_REQUIRED;
754         ObjectRef *ref = checkobject(L, 1);
755         LuaEntitySAO *co = getluaobject(ref);
756         if(co == NULL) return 0;
757         // Do it
758         v3f v = co->getVelocity();
759         pushFloatPos(L, v);
760         return 1;
761 }
762
763 // setacceleration(self, {x=num, y=num, z=num})
764 int ObjectRef::l_setacceleration(lua_State *L)
765 {
766         NO_MAP_LOCK_REQUIRED;
767         ObjectRef *ref = checkobject(L, 1);
768         LuaEntitySAO *co = getluaobject(ref);
769         if(co == NULL) return 0;
770         // pos
771         v3f pos = checkFloatPos(L, 2);
772         // Do it
773         co->setAcceleration(pos);
774         return 0;
775 }
776
777 // getacceleration(self)
778 int ObjectRef::l_getacceleration(lua_State *L)
779 {
780         NO_MAP_LOCK_REQUIRED;
781         ObjectRef *ref = checkobject(L, 1);
782         LuaEntitySAO *co = getluaobject(ref);
783         if(co == NULL) return 0;
784         // Do it
785         v3f v = co->getAcceleration();
786         pushFloatPos(L, v);
787         return 1;
788 }
789
790 // setyaw(self, radians)
791 int ObjectRef::l_setyaw(lua_State *L)
792 {
793         NO_MAP_LOCK_REQUIRED;
794         ObjectRef *ref = checkobject(L, 1);
795         LuaEntitySAO *co = getluaobject(ref);
796         if(co == NULL) return 0;
797         float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
798         // Do it
799         co->setYaw(yaw);
800         return 0;
801 }
802
803 // getyaw(self)
804 int ObjectRef::l_getyaw(lua_State *L)
805 {
806         NO_MAP_LOCK_REQUIRED;
807         ObjectRef *ref = checkobject(L, 1);
808         LuaEntitySAO *co = getluaobject(ref);
809         if(co == NULL) return 0;
810         // Do it
811         float yaw = co->getYaw() * core::DEGTORAD;
812         lua_pushnumber(L, yaw);
813         return 1;
814 }
815
816 // settexturemod(self, mod)
817 int ObjectRef::l_settexturemod(lua_State *L)
818 {
819         NO_MAP_LOCK_REQUIRED;
820         ObjectRef *ref = checkobject(L, 1);
821         LuaEntitySAO *co = getluaobject(ref);
822         if(co == NULL) return 0;
823         // Do it
824         std::string mod = luaL_checkstring(L, 2);
825         co->setTextureMod(mod);
826         return 0;
827 }
828
829 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
830 //           select_horiz_by_yawpitch=false)
831 int ObjectRef::l_setsprite(lua_State *L)
832 {
833         NO_MAP_LOCK_REQUIRED;
834         ObjectRef *ref = checkobject(L, 1);
835         LuaEntitySAO *co = getluaobject(ref);
836         if(co == NULL) return 0;
837         // Do it
838         v2s16 p(0,0);
839         if(!lua_isnil(L, 2))
840                 p = read_v2s16(L, 2);
841         int num_frames = 1;
842         if(!lua_isnil(L, 3))
843                 num_frames = lua_tonumber(L, 3);
844         float framelength = 0.2;
845         if(!lua_isnil(L, 4))
846                 framelength = lua_tonumber(L, 4);
847         bool select_horiz_by_yawpitch = false;
848         if(!lua_isnil(L, 5))
849                 select_horiz_by_yawpitch = lua_toboolean(L, 5);
850         co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
851         return 0;
852 }
853
854 // DEPRECATED
855 // get_entity_name(self)
856 int ObjectRef::l_get_entity_name(lua_State *L)
857 {
858         NO_MAP_LOCK_REQUIRED;
859         ObjectRef *ref = checkobject(L, 1);
860         LuaEntitySAO *co = getluaobject(ref);
861         log_deprecated(L,"Deprecated call to \"get_entity_name");
862         if(co == NULL) return 0;
863         // Do it
864         std::string name = co->getName();
865         lua_pushstring(L, name.c_str());
866         return 1;
867 }
868
869 // get_luaentity(self)
870 int ObjectRef::l_get_luaentity(lua_State *L)
871 {
872         NO_MAP_LOCK_REQUIRED;
873         ObjectRef *ref = checkobject(L, 1);
874         LuaEntitySAO *co = getluaobject(ref);
875         if(co == NULL) return 0;
876         // Do it
877         luaentity_get(L, co->getId());
878         return 1;
879 }
880
881 /* Player-only */
882
883 // is_player_connected(self)
884 int ObjectRef::l_is_player_connected(lua_State *L)
885 {
886         NO_MAP_LOCK_REQUIRED;
887         ObjectRef *ref = checkobject(L, 1);
888         Player *player = getplayer(ref);
889         lua_pushboolean(L, (player != NULL && player->peer_id != 0));
890         return 1;
891 }
892
893 // get_player_name(self)
894 int ObjectRef::l_get_player_name(lua_State *L)
895 {
896         NO_MAP_LOCK_REQUIRED;
897         ObjectRef *ref = checkobject(L, 1);
898         Player *player = getplayer(ref);
899         if(player == NULL){
900                 lua_pushlstring(L, "", 0);
901                 return 1;
902         }
903         // Do it
904         lua_pushstring(L, player->getName());
905         return 1;
906 }
907
908 // get_look_dir(self)
909 int ObjectRef::l_get_look_dir(lua_State *L)
910 {
911         NO_MAP_LOCK_REQUIRED;
912         ObjectRef *ref = checkobject(L, 1);
913         Player *player = getplayer(ref);
914         if(player == NULL) return 0;
915         // Do it
916         float pitch = player->getRadPitch();
917         float yaw = player->getRadYaw();
918         v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw));
919         push_v3f(L, v);
920         return 1;
921 }
922
923 // get_look_pitch(self)
924 int ObjectRef::l_get_look_pitch(lua_State *L)
925 {
926         NO_MAP_LOCK_REQUIRED;
927         ObjectRef *ref = checkobject(L, 1);
928         Player *player = getplayer(ref);
929         if(player == NULL) return 0;
930         // Do it
931         lua_pushnumber(L, player->getRadPitch());
932         return 1;
933 }
934
935 // get_look_yaw(self)
936 int ObjectRef::l_get_look_yaw(lua_State *L)
937 {
938         NO_MAP_LOCK_REQUIRED;
939         ObjectRef *ref = checkobject(L, 1);
940         Player *player = getplayer(ref);
941         if(player == NULL) return 0;
942         // Do it
943         lua_pushnumber(L, player->getRadYaw());
944         return 1;
945 }
946
947 // set_look_pitch(self, radians)
948 int ObjectRef::l_set_look_pitch(lua_State *L)
949 {
950         NO_MAP_LOCK_REQUIRED;
951         ObjectRef *ref = checkobject(L, 1);
952         PlayerSAO* co = getplayersao(ref);
953         if(co == NULL) return 0;
954         float pitch = luaL_checknumber(L, 2) * core::RADTODEG;
955         // Do it
956         co->setPitch(pitch);
957         return 1;
958 }
959
960 // set_look_yaw(self, radians)
961 int ObjectRef::l_set_look_yaw(lua_State *L)
962 {
963         NO_MAP_LOCK_REQUIRED;
964         ObjectRef *ref = checkobject(L, 1);
965         PlayerSAO* co = getplayersao(ref);
966         if(co == NULL) return 0;
967         float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
968         // Do it
969         co->setYaw(yaw);
970         return 1;
971 }
972
973 // set_breath(self, breath)
974 int ObjectRef::l_set_breath(lua_State *L)
975 {
976         NO_MAP_LOCK_REQUIRED;
977         ObjectRef *ref = checkobject(L, 1);
978         PlayerSAO* co = getplayersao(ref);
979         if(co == NULL) return 0;
980         u16 breath = luaL_checknumber(L, 2);
981         // Do it
982         co->setBreath(breath);
983
984         // If the object is a player sent the breath to client
985         if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
986                         getServer(L)->SendPlayerBreath(((PlayerSAO*)co)->getPeerID());
987
988         return 0;
989 }
990
991 // get_breath(self)
992 int ObjectRef::l_get_breath(lua_State *L)
993 {
994         NO_MAP_LOCK_REQUIRED;
995         ObjectRef *ref = checkobject(L, 1);
996         PlayerSAO* co = getplayersao(ref);
997         if(co == NULL) return 0;
998         // Do it
999         u16 breath = co->getBreath();
1000         lua_pushinteger (L, breath);
1001         return 1;
1002 }
1003
1004 // set_inventory_formspec(self, formspec)
1005 int ObjectRef::l_set_inventory_formspec(lua_State *L)
1006 {
1007         NO_MAP_LOCK_REQUIRED;
1008         ObjectRef *ref = checkobject(L, 1);
1009         Player *player = getplayer(ref);
1010         if(player == NULL) return 0;
1011         std::string formspec = luaL_checkstring(L, 2);
1012
1013         player->inventory_formspec = formspec;
1014         getServer(L)->reportInventoryFormspecModified(player->getName());
1015         lua_pushboolean(L, true);
1016         return 1;
1017 }
1018
1019 // get_inventory_formspec(self) -> formspec
1020 int ObjectRef::l_get_inventory_formspec(lua_State *L)
1021 {
1022         NO_MAP_LOCK_REQUIRED;
1023         ObjectRef *ref = checkobject(L, 1);
1024         Player *player = getplayer(ref);
1025         if(player == NULL) return 0;
1026
1027         std::string formspec = player->inventory_formspec;
1028         lua_pushlstring(L, formspec.c_str(), formspec.size());
1029         return 1;
1030 }
1031
1032 // get_player_control(self)
1033 int ObjectRef::l_get_player_control(lua_State *L)
1034 {
1035         NO_MAP_LOCK_REQUIRED;
1036         ObjectRef *ref = checkobject(L, 1);
1037         Player *player = getplayer(ref);
1038         if(player == NULL){
1039                 lua_pushlstring(L, "", 0);
1040                 return 1;
1041         }
1042         // Do it
1043         PlayerControl control = player->getPlayerControl();
1044         lua_newtable(L);
1045         lua_pushboolean(L, control.up);
1046         lua_setfield(L, -2, "up");
1047         lua_pushboolean(L, control.down);
1048         lua_setfield(L, -2, "down");
1049         lua_pushboolean(L, control.left);
1050         lua_setfield(L, -2, "left");
1051         lua_pushboolean(L, control.right);
1052         lua_setfield(L, -2, "right");
1053         lua_pushboolean(L, control.jump);
1054         lua_setfield(L, -2, "jump");
1055         lua_pushboolean(L, control.aux1);
1056         lua_setfield(L, -2, "aux1");
1057         lua_pushboolean(L, control.sneak);
1058         lua_setfield(L, -2, "sneak");
1059         lua_pushboolean(L, control.LMB);
1060         lua_setfield(L, -2, "LMB");
1061         lua_pushboolean(L, control.RMB);
1062         lua_setfield(L, -2, "RMB");
1063         return 1;
1064 }
1065
1066 // get_player_control_bits(self)
1067 int ObjectRef::l_get_player_control_bits(lua_State *L)
1068 {
1069         NO_MAP_LOCK_REQUIRED;
1070         ObjectRef *ref = checkobject(L, 1);
1071         Player *player = getplayer(ref);
1072         if(player == NULL){
1073                 lua_pushlstring(L, "", 0);
1074                 return 1;
1075         }
1076         // Do it
1077         lua_pushnumber(L, player->keyPressed);
1078         return 1;
1079 }
1080
1081 // hud_add(self, form)
1082 int ObjectRef::l_hud_add(lua_State *L)
1083 {
1084         ObjectRef *ref = checkobject(L, 1);
1085         Player *player = getplayer(ref);
1086         if (player == NULL)
1087                 return 0;
1088
1089         HudElement *elem = new HudElement;
1090
1091         elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type",
1092                                                                 es_HudElementType, HUD_ELEM_TEXT);
1093
1094         lua_getfield(L, 2, "position");
1095         elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1096         lua_pop(L, 1);
1097
1098         lua_getfield(L, 2, "scale");
1099         elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1100         lua_pop(L, 1);
1101
1102         lua_getfield(L, 2, "size");
1103         elem->size = lua_istable(L, -1) ? read_v2s32(L, -1) : v2s32();
1104         lua_pop(L, 1);
1105
1106         elem->name   = getstringfield_default(L, 2, "name", "");
1107         elem->text   = getstringfield_default(L, 2, "text", "");
1108         elem->number = getintfield_default(L, 2, "number", 0);
1109         elem->item   = getintfield_default(L, 2, "item", 0);
1110         elem->dir    = getintfield_default(L, 2, "direction", 0);
1111
1112         // Deprecated, only for compatibility's sake
1113         if (elem->dir == 0)
1114                 elem->dir = getintfield_default(L, 2, "dir", 0);
1115
1116         lua_getfield(L, 2, "alignment");
1117         elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1118         lua_pop(L, 1);
1119
1120         lua_getfield(L, 2, "offset");
1121         elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1122         lua_pop(L, 1);
1123
1124         lua_getfield(L, 2, "world_pos");
1125         elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f();
1126         lua_pop(L, 1);
1127
1128         /* check for known deprecated element usage */
1129         if ((elem->type  == HUD_ELEM_STATBAR) && (elem->size == v2s32())) {
1130                 log_deprecated(L,"Deprecated usage of statbar without size!");
1131         }
1132
1133         u32 id = getServer(L)->hudAdd(player, elem);
1134         if (id == (u32)-1) {
1135                 delete elem;
1136                 return 0;
1137         }
1138
1139         lua_pushnumber(L, id);
1140         return 1;
1141 }
1142
1143 // hud_remove(self, id)
1144 int ObjectRef::l_hud_remove(lua_State *L)
1145 {
1146         ObjectRef *ref = checkobject(L, 1);
1147         Player *player = getplayer(ref);
1148         if (player == NULL)
1149                 return 0;
1150
1151         u32 id = -1;
1152         if (!lua_isnil(L, 2))
1153                 id = lua_tonumber(L, 2);
1154
1155         if (!getServer(L)->hudRemove(player, id))
1156                 return 0;
1157
1158         lua_pushboolean(L, true);
1159         return 1;
1160 }
1161
1162 // hud_change(self, id, stat, data)
1163 int ObjectRef::l_hud_change(lua_State *L)
1164 {
1165         ObjectRef *ref = checkobject(L, 1);
1166         Player *player = getplayer(ref);
1167         if (player == NULL)
1168                 return 0;
1169
1170         u32 id = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : -1;
1171
1172         HudElement *e = player->getHud(id);
1173         if (!e)
1174                 return 0;
1175
1176         HudElementStat stat = HUD_STAT_NUMBER;
1177         if (lua_isstring(L, 3)) {
1178                 int statint;
1179                 std::string statstr = lua_tostring(L, 3);
1180                 stat = string_to_enum(es_HudElementStat, statint, statstr) ?
1181                                 (HudElementStat)statint : HUD_STAT_NUMBER;
1182         }
1183
1184         void *value = NULL;
1185         switch (stat) {
1186                 case HUD_STAT_POS:
1187                         e->pos = read_v2f(L, 4);
1188                         value = &e->pos;
1189                         break;
1190                 case HUD_STAT_NAME:
1191                         e->name = luaL_checkstring(L, 4);
1192                         value = &e->name;
1193                         break;
1194                 case HUD_STAT_SCALE:
1195                         e->scale = read_v2f(L, 4);
1196                         value = &e->scale;
1197                         break;
1198                 case HUD_STAT_TEXT:
1199                         e->text = luaL_checkstring(L, 4);
1200                         value = &e->text;
1201                         break;
1202                 case HUD_STAT_NUMBER:
1203                         e->number = luaL_checknumber(L, 4);
1204                         value = &e->number;
1205                         break;
1206                 case HUD_STAT_ITEM:
1207                         e->item = luaL_checknumber(L, 4);
1208                         value = &e->item;
1209                         break;
1210                 case HUD_STAT_DIR:
1211                         e->dir = luaL_checknumber(L, 4);
1212                         value = &e->dir;
1213                         break;
1214                 case HUD_STAT_ALIGN:
1215                         e->align = read_v2f(L, 4);
1216                         value = &e->align;
1217                         break;
1218                 case HUD_STAT_OFFSET:
1219                         e->offset = read_v2f(L, 4);
1220                         value = &e->offset;
1221                         break;
1222                 case HUD_STAT_WORLD_POS:
1223                         e->world_pos = read_v3f(L, 4);
1224                         value = &e->world_pos;
1225                         break;
1226                 case HUD_STAT_SIZE:
1227                         e->size = read_v2s32(L, 4);
1228                         value = &e->size;
1229                         break;
1230         }
1231
1232         getServer(L)->hudChange(player, id, stat, value);
1233
1234         lua_pushboolean(L, true);
1235         return 1;
1236 }
1237
1238 // hud_get(self, id)
1239 int ObjectRef::l_hud_get(lua_State *L)
1240 {
1241         ObjectRef *ref = checkobject(L, 1);
1242         Player *player = getplayer(ref);
1243         if (player == NULL)
1244                 return 0;
1245
1246         u32 id = lua_tonumber(L, -1);
1247
1248         HudElement *e = player->getHud(id);
1249         if (!e)
1250                 return 0;
1251
1252         lua_newtable(L);
1253
1254         lua_pushstring(L, es_HudElementType[(u8)e->type].str);
1255         lua_setfield(L, -2, "type");
1256
1257         push_v2f(L, e->pos);
1258         lua_setfield(L, -2, "position");
1259
1260         lua_pushstring(L, e->name.c_str());
1261         lua_setfield(L, -2, "name");
1262
1263         push_v2f(L, e->scale);
1264         lua_setfield(L, -2, "scale");
1265
1266         lua_pushstring(L, e->text.c_str());
1267         lua_setfield(L, -2, "text");
1268
1269         lua_pushnumber(L, e->number);
1270         lua_setfield(L, -2, "number");
1271
1272         lua_pushnumber(L, e->item);
1273         lua_setfield(L, -2, "item");
1274
1275         lua_pushnumber(L, e->dir);
1276         lua_setfield(L, -2, "direction");
1277
1278         // Deprecated, only for compatibility's sake
1279         lua_pushnumber(L, e->dir);
1280         lua_setfield(L, -2, "dir");
1281
1282         push_v3f(L, e->world_pos);
1283         lua_setfield(L, -2, "world_pos");
1284
1285         return 1;
1286 }
1287
1288 // hud_set_flags(self, flags)
1289 int ObjectRef::l_hud_set_flags(lua_State *L)
1290 {
1291         ObjectRef *ref = checkobject(L, 1);
1292         Player *player = getplayer(ref);
1293         if (player == NULL)
1294                 return 0;
1295
1296         u32 flags = 0;
1297         u32 mask  = 0;
1298         bool flag;
1299
1300         const EnumString *esp = es_HudBuiltinElement;
1301         for (int i = 0; esp[i].str; i++) {
1302                 if (getboolfield(L, 2, esp[i].str, flag)) {
1303                         flags |= esp[i].num * flag;
1304                         mask  |= esp[i].num;
1305                 }
1306         }
1307         if (!getServer(L)->hudSetFlags(player, flags, mask))
1308                 return 0;
1309
1310         lua_pushboolean(L, true);
1311         return 1;
1312 }
1313
1314 int ObjectRef::l_hud_get_flags(lua_State *L)
1315 {
1316         ObjectRef *ref = checkobject(L, 1);
1317         Player *player = getplayer(ref);
1318         if (player == NULL)
1319                 return 0;
1320
1321         lua_newtable(L);
1322         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE);
1323         lua_setfield(L, -2, "hotbar");
1324         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE);
1325         lua_setfield(L, -2, "healthbar");
1326         lua_pushboolean(L, player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE);
1327         lua_setfield(L, -2, "crosshair");
1328         lua_pushboolean(L, player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE);
1329         lua_setfield(L, -2, "wielditem");
1330         lua_pushboolean(L, player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE);
1331         lua_setfield(L, -2, "breathbar");
1332
1333         return 1;
1334 }
1335
1336 // hud_set_hotbar_itemcount(self, hotbar_itemcount)
1337 int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
1338 {
1339         ObjectRef *ref = checkobject(L, 1);
1340         Player *player = getplayer(ref);
1341         if (player == NULL)
1342                 return 0;
1343
1344         s32 hotbar_itemcount = lua_tonumber(L, 2);
1345
1346         if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
1347                 return 0;
1348
1349         lua_pushboolean(L, true);
1350         return 1;
1351 }
1352
1353 // hud_get_hotbar_itemcount(self)
1354 int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
1355 {
1356         ObjectRef *ref = checkobject(L, 1);
1357         Player *player = getplayer(ref);
1358         if (player == NULL)
1359                 return 0;
1360
1361         s32 hotbar_itemcount = getServer(L)->hudGetHotbarItemcount(player);
1362
1363         lua_pushnumber(L, hotbar_itemcount);
1364         return 1;
1365 }
1366
1367 // hud_set_hotbar_image(self, name)
1368 int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
1369 {
1370         ObjectRef *ref = checkobject(L, 1);
1371         Player *player = getplayer(ref);
1372         if (player == NULL)
1373                 return 0;
1374
1375         std::string name = lua_tostring(L, 2);
1376
1377         getServer(L)->hudSetHotbarImage(player, name);
1378         return 1;
1379 }
1380
1381 // hud_get_hotbar_image(self)
1382 int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
1383 {
1384         ObjectRef *ref = checkobject(L, 1);
1385         Player *player = getplayer(ref);
1386         if (player == NULL)
1387                 return 0;
1388
1389         std::string name = getServer(L)->hudGetHotbarImage(player);
1390         lua_pushlstring(L, name.c_str(), name.size());
1391         return 1;
1392 }
1393
1394 // hud_set_hotbar_selected_image(self, name)
1395 int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
1396 {
1397         ObjectRef *ref = checkobject(L, 1);
1398         Player *player = getplayer(ref);
1399         if (player == NULL)
1400                 return 0;
1401
1402         std::string name = lua_tostring(L, 2);
1403
1404         getServer(L)->hudSetHotbarSelectedImage(player, name);
1405         return 1;
1406 }
1407
1408 // hud_get_hotbar_selected_image(self)
1409 int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
1410 {
1411         ObjectRef *ref = checkobject(L, 1);
1412         Player *player = getplayer(ref);
1413         if (player == NULL)
1414                 return 0;
1415
1416         std::string name = getServer(L)->hudGetHotbarSelectedImage(player);
1417         lua_pushlstring(L, name.c_str(), name.size());
1418         return 1;
1419 }
1420
1421 // set_sky(self, bgcolor, type, list)
1422 int ObjectRef::l_set_sky(lua_State *L)
1423 {
1424         ObjectRef *ref = checkobject(L, 1);
1425         Player *player = getplayer(ref);
1426         if (player == NULL)
1427                 return 0;
1428
1429         video::SColor bgcolor(255,255,255,255);
1430         read_color(L, 2, &bgcolor);
1431
1432         std::string type = luaL_checkstring(L, 3);
1433
1434         std::vector<std::string> params;
1435         if (lua_istable(L, 4)) {
1436                 int table = lua_gettop(L);
1437                 lua_pushnil(L);
1438                 while (lua_next(L, table) != 0) {
1439                         // key at index -2 and value at index -1
1440                         if (lua_isstring(L, -1))
1441                                 params.push_back(lua_tostring(L, -1));
1442                         else
1443                                 params.push_back("");
1444                         // removes value, keeps key for next iteration
1445                         lua_pop(L, 1);
1446                 }
1447         }
1448
1449         if (type == "skybox" && params.size() != 6)
1450                 throw LuaError("skybox expects 6 textures");
1451
1452         if (!getServer(L)->setSky(player, bgcolor, type, params))
1453                 return 0;
1454
1455         lua_pushboolean(L, true);
1456         return 1;
1457 }
1458
1459 // get_sky(self)
1460 int ObjectRef::l_get_sky(lua_State *L)
1461 {
1462         ObjectRef *ref = checkobject(L, 1);
1463         Player *player = getplayer(ref);
1464         if (player == NULL)
1465                 return 0;
1466         video::SColor bgcolor(255, 255, 255, 255);
1467         std::string type;
1468         std::vector<std::string> params;
1469
1470         player->getSky(&bgcolor, &type, &params);
1471         type = type == "" ? "regular" : type;
1472
1473         push_ARGB8(L, bgcolor);
1474         lua_pushlstring(L, type.c_str(), type.size());
1475         lua_newtable(L);
1476         s16 i = 1;
1477         for (std::vector<std::string>::iterator it = params.begin();
1478                         it != params.end(); ++it) {
1479                 lua_pushlstring(L, it->c_str(), it->size());
1480                 lua_rawseti(L, -2, i);
1481                 i++;
1482         }
1483         return 3;
1484 }
1485
1486 // override_day_night_ratio(self, brightness=0...1)
1487 int ObjectRef::l_override_day_night_ratio(lua_State *L)
1488 {
1489         ObjectRef *ref = checkobject(L, 1);
1490         Player *player = getplayer(ref);
1491         if (player == NULL)
1492                 return 0;
1493
1494         bool do_override = false;
1495         float ratio = 0.0f;
1496         if (!lua_isnil(L, 2)){
1497                 do_override = true;
1498                 ratio = luaL_checknumber(L, 2);
1499         }
1500
1501         if (!getServer(L)->overrideDayNightRatio(player, do_override, ratio))
1502                 return 0;
1503
1504         lua_pushboolean(L, true);
1505         return 1;
1506 }
1507
1508 // get_day_night_ratio(self)
1509 int ObjectRef::l_get_day_night_ratio(lua_State *L)
1510 {
1511         ObjectRef *ref = checkobject(L, 1);
1512         Player *player = getplayer(ref);
1513         if (player == NULL)
1514                 return 0;
1515
1516         bool do_override;
1517         float ratio;
1518         player->getDayNightRatio(&do_override, &ratio);
1519
1520         if (do_override)
1521                 lua_pushnumber(L, ratio);
1522         else
1523                 lua_pushnil(L);
1524
1525         return 1;
1526 }
1527
1528 // set_nametag_attributes(self, attributes)
1529 int ObjectRef::l_set_nametag_attributes(lua_State *L)
1530 {
1531         NO_MAP_LOCK_REQUIRED;
1532         ObjectRef *ref = checkobject(L, 1);
1533         PlayerSAO *playersao = getplayersao(ref);
1534         if (playersao == NULL)
1535                 return 0;
1536
1537         lua_getfield(L, 2, "color");
1538         if (!lua_isnil(L, -1)) {
1539                 video::SColor color = playersao->getNametagColor();
1540                 if (!read_color(L, -1, &color))
1541                         return 0;
1542                 playersao->setNametagColor(color);
1543         }
1544
1545         lua_pushboolean(L, true);
1546         return 1;
1547 }
1548
1549 // get_nametag_attributes(self)
1550 int ObjectRef::l_get_nametag_attributes(lua_State *L)
1551 {
1552         NO_MAP_LOCK_REQUIRED;
1553         ObjectRef *ref = checkobject(L, 1);
1554         PlayerSAO *playersao = getplayersao(ref);
1555         if (playersao == NULL)
1556                 return 0;
1557
1558         video::SColor color = playersao->getNametagColor();
1559
1560         lua_newtable(L);
1561         push_ARGB8(L, color);
1562         lua_setfield(L, -2, "color");
1563
1564         return 1;
1565 }
1566
1567 ObjectRef::ObjectRef(ServerActiveObject *object):
1568         m_object(object)
1569 {
1570         //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
1571 }
1572
1573 ObjectRef::~ObjectRef()
1574 {
1575         /*if(m_object)
1576                 infostream<<"ObjectRef destructing for id="
1577                                 <<m_object->getId()<<std::endl;
1578         else
1579                 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
1580 }
1581
1582 // Creates an ObjectRef and leaves it on top of stack
1583 // Not callable from Lua; all references are created on the C side.
1584 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
1585 {
1586         ObjectRef *o = new ObjectRef(object);
1587         //infostream<<"ObjectRef::create: o="<<o<<std::endl;
1588         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1589         luaL_getmetatable(L, className);
1590         lua_setmetatable(L, -2);
1591 }
1592
1593 void ObjectRef::set_null(lua_State *L)
1594 {
1595         ObjectRef *o = checkobject(L, -1);
1596         o->m_object = NULL;
1597 }
1598
1599 void ObjectRef::Register(lua_State *L)
1600 {
1601         lua_newtable(L);
1602         int methodtable = lua_gettop(L);
1603         luaL_newmetatable(L, className);
1604         int metatable = lua_gettop(L);
1605
1606         lua_pushliteral(L, "__metatable");
1607         lua_pushvalue(L, methodtable);
1608         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
1609
1610         lua_pushliteral(L, "__index");
1611         lua_pushvalue(L, methodtable);
1612         lua_settable(L, metatable);
1613
1614         lua_pushliteral(L, "__gc");
1615         lua_pushcfunction(L, gc_object);
1616         lua_settable(L, metatable);
1617
1618         lua_pop(L, 1);  // drop metatable
1619
1620         luaL_openlib(L, 0, methods, 0);  // fill methodtable
1621         lua_pop(L, 1);  // drop methodtable
1622
1623         // Cannot be created from Lua
1624         //lua_register(L, className, create_object);
1625 }
1626
1627 const char ObjectRef::className[] = "ObjectRef";
1628 const luaL_reg ObjectRef::methods[] = {
1629         // ServerActiveObject
1630         luamethod(ObjectRef, remove),
1631         luamethod(ObjectRef, getpos),
1632         luamethod(ObjectRef, setpos),
1633         luamethod(ObjectRef, moveto),
1634         luamethod(ObjectRef, punch),
1635         luamethod(ObjectRef, right_click),
1636         luamethod(ObjectRef, set_hp),
1637         luamethod(ObjectRef, get_hp),
1638         luamethod(ObjectRef, get_inventory),
1639         luamethod(ObjectRef, get_wield_list),
1640         luamethod(ObjectRef, get_wield_index),
1641         luamethod(ObjectRef, get_wielded_item),
1642         luamethod(ObjectRef, set_wielded_item),
1643         luamethod(ObjectRef, set_armor_groups),
1644         luamethod(ObjectRef, get_armor_groups),
1645         luamethod(ObjectRef, set_animation),
1646         luamethod(ObjectRef, get_animation),
1647         luamethod(ObjectRef, set_bone_position),
1648         luamethod(ObjectRef, get_bone_position),
1649         luamethod(ObjectRef, set_attach),
1650         luamethod(ObjectRef, get_attach),
1651         luamethod(ObjectRef, set_detach),
1652         luamethod(ObjectRef, set_properties),
1653         luamethod(ObjectRef, get_properties),
1654         // LuaEntitySAO-only
1655         luamethod(ObjectRef, setvelocity),
1656         luamethod(ObjectRef, getvelocity),
1657         luamethod(ObjectRef, setacceleration),
1658         luamethod(ObjectRef, getacceleration),
1659         luamethod(ObjectRef, setyaw),
1660         luamethod(ObjectRef, getyaw),
1661         luamethod(ObjectRef, settexturemod),
1662         luamethod(ObjectRef, setsprite),
1663         luamethod(ObjectRef, get_entity_name),
1664         luamethod(ObjectRef, get_luaentity),
1665         // Player-only
1666         luamethod(ObjectRef, is_player),
1667         luamethod(ObjectRef, is_player_connected),
1668         luamethod(ObjectRef, get_player_name),
1669         luamethod(ObjectRef, get_look_dir),
1670         luamethod(ObjectRef, get_look_pitch),
1671         luamethod(ObjectRef, get_look_yaw),
1672         luamethod(ObjectRef, set_look_yaw),
1673         luamethod(ObjectRef, set_look_pitch),
1674         luamethod(ObjectRef, get_breath),
1675         luamethod(ObjectRef, set_breath),
1676         luamethod(ObjectRef, set_inventory_formspec),
1677         luamethod(ObjectRef, get_inventory_formspec),
1678         luamethod(ObjectRef, get_player_control),
1679         luamethod(ObjectRef, get_player_control_bits),
1680         luamethod(ObjectRef, set_physics_override),
1681         luamethod(ObjectRef, get_physics_override),
1682         luamethod(ObjectRef, hud_add),
1683         luamethod(ObjectRef, hud_remove),
1684         luamethod(ObjectRef, hud_change),
1685         luamethod(ObjectRef, hud_get),
1686         luamethod(ObjectRef, hud_set_flags),
1687         luamethod(ObjectRef, hud_get_flags),
1688         luamethod(ObjectRef, hud_set_hotbar_itemcount),
1689         luamethod(ObjectRef, hud_get_hotbar_itemcount),
1690         luamethod(ObjectRef, hud_set_hotbar_image),
1691         luamethod(ObjectRef, hud_get_hotbar_image),
1692         luamethod(ObjectRef, hud_set_hotbar_selected_image),
1693         luamethod(ObjectRef, hud_get_hotbar_selected_image),
1694         luamethod(ObjectRef, set_sky),
1695         luamethod(ObjectRef, get_sky),
1696         luamethod(ObjectRef, override_day_night_ratio),
1697         luamethod(ObjectRef, get_day_night_ratio),
1698         luamethod(ObjectRef, set_local_animation),
1699         luamethod(ObjectRef, get_local_animation),
1700         luamethod(ObjectRef, set_eye_offset),
1701         luamethod(ObjectRef, get_eye_offset),
1702         luamethod(ObjectRef, set_nametag_attributes),
1703         luamethod(ObjectRef, get_nametag_attributes),
1704         {0,0}
1705 };