]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_object.cpp
Mapgen objects: Enable heatmap and humidmap for all biome api mapgens
[dragonfireclient.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)
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         co->setAnimation(frames, frame_speed, frame_blend);
470         return 0;
471 }
472
473 // get_animation(self)
474 int ObjectRef::l_get_animation(lua_State *L)
475 {
476         NO_MAP_LOCK_REQUIRED;
477         ObjectRef *ref = checkobject(L, 1);
478         ServerActiveObject *co = getobject(ref);
479         if (co == NULL)
480                 return 0;
481         // Do it
482         v2f frames = v2f(1,1);
483         float frame_speed = 15;
484         float frame_blend = 0;
485         co->getAnimation(&frames, &frame_speed, &frame_blend);
486
487         push_v2f(L, frames);
488         lua_pushnumber(L, frame_speed);
489         lua_pushnumber(L, frame_blend);
490         return 3;
491 }
492
493 // set_local_animation(self, {stand/idle}, {walk}, {dig}, {walk+dig}, frame_speed)
494 int ObjectRef::l_set_local_animation(lua_State *L)
495 {
496         //NO_MAP_LOCK_REQUIRED;
497         ObjectRef *ref = checkobject(L, 1);
498         Player *player = getplayer(ref);
499         if (player == NULL)
500                 return 0;
501         // Do it
502         v2s32 frames[4];
503         for (int i=0;i<4;i++) {
504                 if(!lua_isnil(L, 2+1))
505                         frames[i] = read_v2s32(L, 2+i);
506         }
507         float frame_speed = 30;
508         if(!lua_isnil(L, 6))
509                 frame_speed = lua_tonumber(L, 6);
510
511         if (!getServer(L)->setLocalPlayerAnimations(player, frames, frame_speed))
512                 return 0;
513
514         lua_pushboolean(L, true);
515         return 0;
516 }
517
518 // get_local_animation(self)
519 int ObjectRef::l_get_local_animation(lua_State *L)
520 {
521         //NO_MAP_LOCK_REQUIRED
522         ObjectRef *ref = checkobject(L, 1);
523         Player *player = getplayer(ref);
524         if (player == NULL)
525                 return 0;
526
527         v2s32 frames[4];
528         float frame_speed;
529         player->getLocalAnimations(frames, &frame_speed);
530
531         for (int i = 0; i < 4; i++) {
532                 push_v2s32(L, frames[i]);
533         }
534
535         lua_pushnumber(L, frame_speed);
536         return 5;
537 }
538
539 // set_eye_offset(self, v3f first pv, v3f third pv)
540 int ObjectRef::l_set_eye_offset(lua_State *L)
541 {
542         //NO_MAP_LOCK_REQUIRED;
543         ObjectRef *ref = checkobject(L, 1);
544         Player *player = getplayer(ref);
545         if (player == NULL)
546                 return 0;
547         // Do it
548         v3f offset_first = v3f(0, 0, 0);
549         v3f offset_third = v3f(0, 0, 0);
550
551         if(!lua_isnil(L, 2))
552                 offset_first = read_v3f(L, 2);
553         if(!lua_isnil(L, 3))
554                 offset_third = read_v3f(L, 3);
555
556         // Prevent abuse of offset values (keep player always visible)
557         offset_third.X = rangelim(offset_third.X,-10,10);
558         offset_third.Z = rangelim(offset_third.Z,-5,5);
559         /* TODO: if possible: improve the camera colision detetion to allow Y <= -1.5) */
560         offset_third.Y = rangelim(offset_third.Y,-10,15); //1.5*BS
561
562         if (!getServer(L)->setPlayerEyeOffset(player, offset_first, offset_third))
563                 return 0;
564
565         lua_pushboolean(L, true);
566         return 0;
567 }
568
569 // get_eye_offset(self)
570 int ObjectRef::l_get_eye_offset(lua_State *L)
571 {
572         //NO_MAP_LOCK_REQUIRED;
573         ObjectRef *ref = checkobject(L, 1);
574         Player *player = getplayer(ref);
575         if (player == NULL)
576                 return 0;
577         // Do it
578         push_v3f(L, player->eye_offset_first);
579         push_v3f(L, player->eye_offset_third);
580         return 2;
581 }
582
583 // set_bone_position(self, std::string bone, v3f position, v3f rotation)
584 int ObjectRef::l_set_bone_position(lua_State *L)
585 {
586         NO_MAP_LOCK_REQUIRED;
587         ObjectRef *ref = checkobject(L, 1);
588         ServerActiveObject *co = getobject(ref);
589         if(co == NULL) return 0;
590         // Do it
591         std::string bone = "";
592         if(!lua_isnil(L, 2))
593                 bone = lua_tostring(L, 2);
594         v3f position = v3f(0, 0, 0);
595         if(!lua_isnil(L, 3))
596                 position = read_v3f(L, 3);
597         v3f rotation = v3f(0, 0, 0);
598         if(!lua_isnil(L, 4))
599                 rotation = read_v3f(L, 4);
600         co->setBonePosition(bone, position, rotation);
601         return 0;
602 }
603
604 // get_bone_position(self, bone)
605 int ObjectRef::l_get_bone_position(lua_State *L)
606 {
607         NO_MAP_LOCK_REQUIRED;
608         ObjectRef *ref = checkobject(L, 1);
609         ServerActiveObject *co = getobject(ref);
610         if (co == NULL)
611                 return 0;
612         // Do it
613         std::string bone = "";
614         if(!lua_isnil(L, 2))
615                 bone = lua_tostring(L, 2);
616
617         v3f position = v3f(0, 0, 0);
618         v3f rotation = v3f(0, 0, 0);
619         co->getBonePosition(bone, &position, &rotation);
620
621         push_v3f(L, position);
622         push_v3f(L, rotation);
623         return 2;
624 }
625
626 // set_attach(self, parent, bone, position, rotation)
627 int ObjectRef::l_set_attach(lua_State *L)
628 {
629         NO_MAP_LOCK_REQUIRED;
630         ObjectRef *ref = checkobject(L, 1);
631         ObjectRef *parent_ref = checkobject(L, 2);
632         ServerActiveObject *co = getobject(ref);
633         ServerActiveObject *parent = getobject(parent_ref);
634         if(co == NULL) return 0;
635         if(parent == NULL) return 0;
636         // Do it
637         std::string bone = "";
638         if(!lua_isnil(L, 3))
639                 bone = lua_tostring(L, 3);
640         v3f position = v3f(0, 0, 0);
641         if(!lua_isnil(L, 4))
642                 position = read_v3f(L, 4);
643         v3f rotation = v3f(0, 0, 0);
644         if(!lua_isnil(L, 5))
645                 rotation = read_v3f(L, 5);
646         co->setAttachment(parent->getId(), bone, position, rotation);
647         return 0;
648 }
649
650 // get_attach(self)
651 int ObjectRef::l_get_attach(lua_State *L)
652 {
653         NO_MAP_LOCK_REQUIRED;
654         GET_ENV_PTR;
655
656         ObjectRef *ref = checkobject(L, 1);
657         ServerActiveObject *co = getobject(ref);
658         if (co == NULL)
659                 return 0;
660
661         // Do it
662         int parent_id = 0;
663         std::string bone = "";
664         v3f position = v3f(0, 0, 0);
665         v3f rotation = v3f(0, 0, 0);
666         co->getAttachment(&parent_id, &bone, &position, &rotation);
667         if (!parent_id)
668                 return 0;
669         ServerActiveObject *parent = env->getActiveObject(parent_id);
670
671         getScriptApiBase(L)->objectrefGetOrCreate(L, parent);
672         lua_pushlstring(L, bone.c_str(), bone.size());
673         push_v3f(L, position);
674         push_v3f(L, rotation);
675         return 4;
676 }
677
678 // set_detach(self)
679 int ObjectRef::l_set_detach(lua_State *L)
680 {
681         NO_MAP_LOCK_REQUIRED;
682         ObjectRef *ref = checkobject(L, 1);
683         ServerActiveObject *co = getobject(ref);
684         if(co == NULL) return 0;
685         // Do it
686         co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0));
687         return 0;
688 }
689
690 // set_properties(self, properties)
691 int ObjectRef::l_set_properties(lua_State *L)
692 {
693         NO_MAP_LOCK_REQUIRED;
694         ObjectRef *ref = checkobject(L, 1);
695         ServerActiveObject *co = getobject(ref);
696         if(co == NULL) return 0;
697         ObjectProperties *prop = co->accessObjectProperties();
698         if(!prop)
699                 return 0;
700         read_object_properties(L, 2, prop);
701         co->notifyObjectPropertiesModified();
702         return 0;
703 }
704
705 // get_properties(self)
706 int ObjectRef::l_get_properties(lua_State *L)
707 {
708         NO_MAP_LOCK_REQUIRED;
709         ObjectRef *ref = checkobject(L, 1);
710         ServerActiveObject *co = getobject(ref);
711         if (co == NULL)
712                 return 0;
713         ObjectProperties *prop = co->accessObjectProperties();
714         if (!prop)
715                 return 0;
716         push_object_properties(L, prop);
717         return 1;
718 }
719
720 // is_player(self)
721 int ObjectRef::l_is_player(lua_State *L)
722 {
723         NO_MAP_LOCK_REQUIRED;
724         ObjectRef *ref = checkobject(L, 1);
725         Player *player = getplayer(ref);
726         lua_pushboolean(L, (player != NULL));
727         return 1;
728 }
729
730 /* LuaEntitySAO-only */
731
732 // setvelocity(self, {x=num, y=num, z=num})
733 int ObjectRef::l_setvelocity(lua_State *L)
734 {
735         NO_MAP_LOCK_REQUIRED;
736         ObjectRef *ref = checkobject(L, 1);
737         LuaEntitySAO *co = getluaobject(ref);
738         if(co == NULL) return 0;
739         v3f pos = checkFloatPos(L, 2);
740         // Do it
741         co->setVelocity(pos);
742         return 0;
743 }
744
745 // getvelocity(self)
746 int ObjectRef::l_getvelocity(lua_State *L)
747 {
748         NO_MAP_LOCK_REQUIRED;
749         ObjectRef *ref = checkobject(L, 1);
750         LuaEntitySAO *co = getluaobject(ref);
751         if(co == NULL) return 0;
752         // Do it
753         v3f v = co->getVelocity();
754         pushFloatPos(L, v);
755         return 1;
756 }
757
758 // setacceleration(self, {x=num, y=num, z=num})
759 int ObjectRef::l_setacceleration(lua_State *L)
760 {
761         NO_MAP_LOCK_REQUIRED;
762         ObjectRef *ref = checkobject(L, 1);
763         LuaEntitySAO *co = getluaobject(ref);
764         if(co == NULL) return 0;
765         // pos
766         v3f pos = checkFloatPos(L, 2);
767         // Do it
768         co->setAcceleration(pos);
769         return 0;
770 }
771
772 // getacceleration(self)
773 int ObjectRef::l_getacceleration(lua_State *L)
774 {
775         NO_MAP_LOCK_REQUIRED;
776         ObjectRef *ref = checkobject(L, 1);
777         LuaEntitySAO *co = getluaobject(ref);
778         if(co == NULL) return 0;
779         // Do it
780         v3f v = co->getAcceleration();
781         pushFloatPos(L, v);
782         return 1;
783 }
784
785 // setyaw(self, radians)
786 int ObjectRef::l_setyaw(lua_State *L)
787 {
788         NO_MAP_LOCK_REQUIRED;
789         ObjectRef *ref = checkobject(L, 1);
790         LuaEntitySAO *co = getluaobject(ref);
791         if(co == NULL) return 0;
792         float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
793         // Do it
794         co->setYaw(yaw);
795         return 0;
796 }
797
798 // getyaw(self)
799 int ObjectRef::l_getyaw(lua_State *L)
800 {
801         NO_MAP_LOCK_REQUIRED;
802         ObjectRef *ref = checkobject(L, 1);
803         LuaEntitySAO *co = getluaobject(ref);
804         if(co == NULL) return 0;
805         // Do it
806         float yaw = co->getYaw() * core::DEGTORAD;
807         lua_pushnumber(L, yaw);
808         return 1;
809 }
810
811 // settexturemod(self, mod)
812 int ObjectRef::l_settexturemod(lua_State *L)
813 {
814         NO_MAP_LOCK_REQUIRED;
815         ObjectRef *ref = checkobject(L, 1);
816         LuaEntitySAO *co = getluaobject(ref);
817         if(co == NULL) return 0;
818         // Do it
819         std::string mod = luaL_checkstring(L, 2);
820         co->setTextureMod(mod);
821         return 0;
822 }
823
824 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
825 //           select_horiz_by_yawpitch=false)
826 int ObjectRef::l_setsprite(lua_State *L)
827 {
828         NO_MAP_LOCK_REQUIRED;
829         ObjectRef *ref = checkobject(L, 1);
830         LuaEntitySAO *co = getluaobject(ref);
831         if(co == NULL) return 0;
832         // Do it
833         v2s16 p(0,0);
834         if(!lua_isnil(L, 2))
835                 p = read_v2s16(L, 2);
836         int num_frames = 1;
837         if(!lua_isnil(L, 3))
838                 num_frames = lua_tonumber(L, 3);
839         float framelength = 0.2;
840         if(!lua_isnil(L, 4))
841                 framelength = lua_tonumber(L, 4);
842         bool select_horiz_by_yawpitch = false;
843         if(!lua_isnil(L, 5))
844                 select_horiz_by_yawpitch = lua_toboolean(L, 5);
845         co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
846         return 0;
847 }
848
849 // DEPRECATED
850 // get_entity_name(self)
851 int ObjectRef::l_get_entity_name(lua_State *L)
852 {
853         NO_MAP_LOCK_REQUIRED;
854         ObjectRef *ref = checkobject(L, 1);
855         LuaEntitySAO *co = getluaobject(ref);
856         log_deprecated(L,"Deprecated call to \"get_entity_name");
857         if(co == NULL) return 0;
858         // Do it
859         std::string name = co->getName();
860         lua_pushstring(L, name.c_str());
861         return 1;
862 }
863
864 // get_luaentity(self)
865 int ObjectRef::l_get_luaentity(lua_State *L)
866 {
867         NO_MAP_LOCK_REQUIRED;
868         ObjectRef *ref = checkobject(L, 1);
869         LuaEntitySAO *co = getluaobject(ref);
870         if(co == NULL) return 0;
871         // Do it
872         luaentity_get(L, co->getId());
873         return 1;
874 }
875
876 /* Player-only */
877
878 // is_player_connected(self)
879 int ObjectRef::l_is_player_connected(lua_State *L)
880 {
881         NO_MAP_LOCK_REQUIRED;
882         ObjectRef *ref = checkobject(L, 1);
883         Player *player = getplayer(ref);
884         lua_pushboolean(L, (player != NULL && player->peer_id != 0));
885         return 1;
886 }
887
888 // get_player_name(self)
889 int ObjectRef::l_get_player_name(lua_State *L)
890 {
891         NO_MAP_LOCK_REQUIRED;
892         ObjectRef *ref = checkobject(L, 1);
893         Player *player = getplayer(ref);
894         if(player == NULL){
895                 lua_pushlstring(L, "", 0);
896                 return 1;
897         }
898         // Do it
899         lua_pushstring(L, player->getName());
900         return 1;
901 }
902
903 // get_look_dir(self)
904 int ObjectRef::l_get_look_dir(lua_State *L)
905 {
906         NO_MAP_LOCK_REQUIRED;
907         ObjectRef *ref = checkobject(L, 1);
908         Player *player = getplayer(ref);
909         if(player == NULL) return 0;
910         // Do it
911         float pitch = player->getRadPitch();
912         float yaw = player->getRadYaw();
913         v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw));
914         push_v3f(L, v);
915         return 1;
916 }
917
918 // get_look_pitch(self)
919 int ObjectRef::l_get_look_pitch(lua_State *L)
920 {
921         NO_MAP_LOCK_REQUIRED;
922         ObjectRef *ref = checkobject(L, 1);
923         Player *player = getplayer(ref);
924         if(player == NULL) return 0;
925         // Do it
926         lua_pushnumber(L, player->getRadPitch());
927         return 1;
928 }
929
930 // get_look_yaw(self)
931 int ObjectRef::l_get_look_yaw(lua_State *L)
932 {
933         NO_MAP_LOCK_REQUIRED;
934         ObjectRef *ref = checkobject(L, 1);
935         Player *player = getplayer(ref);
936         if(player == NULL) return 0;
937         // Do it
938         lua_pushnumber(L, player->getRadYaw());
939         return 1;
940 }
941
942 // set_look_pitch(self, radians)
943 int ObjectRef::l_set_look_pitch(lua_State *L)
944 {
945         NO_MAP_LOCK_REQUIRED;
946         ObjectRef *ref = checkobject(L, 1);
947         PlayerSAO* co = getplayersao(ref);
948         if(co == NULL) return 0;
949         float pitch = luaL_checknumber(L, 2) * core::RADTODEG;
950         // Do it
951         co->setPitch(pitch);
952         return 1;
953 }
954
955 // set_look_yaw(self, radians)
956 int ObjectRef::l_set_look_yaw(lua_State *L)
957 {
958         NO_MAP_LOCK_REQUIRED;
959         ObjectRef *ref = checkobject(L, 1);
960         PlayerSAO* co = getplayersao(ref);
961         if(co == NULL) return 0;
962         float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
963         // Do it
964         co->setYaw(yaw);
965         return 1;
966 }
967
968 // set_breath(self, breath)
969 int ObjectRef::l_set_breath(lua_State *L)
970 {
971         NO_MAP_LOCK_REQUIRED;
972         ObjectRef *ref = checkobject(L, 1);
973         PlayerSAO* co = getplayersao(ref);
974         if(co == NULL) return 0;
975         u16 breath = luaL_checknumber(L, 2);
976         // Do it
977         co->setBreath(breath);
978
979         // If the object is a player sent the breath to client
980         if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
981                         getServer(L)->SendPlayerBreath(((PlayerSAO*)co)->getPeerID());
982
983         return 0;
984 }
985
986 // get_breath(self)
987 int ObjectRef::l_get_breath(lua_State *L)
988 {
989         NO_MAP_LOCK_REQUIRED;
990         ObjectRef *ref = checkobject(L, 1);
991         PlayerSAO* co = getplayersao(ref);
992         if(co == NULL) return 0;
993         // Do it
994         u16 breath = co->getBreath();
995         lua_pushinteger (L, breath);
996         return 1;
997 }
998
999 // set_inventory_formspec(self, formspec)
1000 int ObjectRef::l_set_inventory_formspec(lua_State *L)
1001 {
1002         NO_MAP_LOCK_REQUIRED;
1003         ObjectRef *ref = checkobject(L, 1);
1004         Player *player = getplayer(ref);
1005         if(player == NULL) return 0;
1006         std::string formspec = luaL_checkstring(L, 2);
1007
1008         player->inventory_formspec = formspec;
1009         getServer(L)->reportInventoryFormspecModified(player->getName());
1010         lua_pushboolean(L, true);
1011         return 1;
1012 }
1013
1014 // get_inventory_formspec(self) -> formspec
1015 int ObjectRef::l_get_inventory_formspec(lua_State *L)
1016 {
1017         NO_MAP_LOCK_REQUIRED;
1018         ObjectRef *ref = checkobject(L, 1);
1019         Player *player = getplayer(ref);
1020         if(player == NULL) return 0;
1021
1022         std::string formspec = player->inventory_formspec;
1023         lua_pushlstring(L, formspec.c_str(), formspec.size());
1024         return 1;
1025 }
1026
1027 // get_player_control(self)
1028 int ObjectRef::l_get_player_control(lua_State *L)
1029 {
1030         NO_MAP_LOCK_REQUIRED;
1031         ObjectRef *ref = checkobject(L, 1);
1032         Player *player = getplayer(ref);
1033         if(player == NULL){
1034                 lua_pushlstring(L, "", 0);
1035                 return 1;
1036         }
1037         // Do it
1038         PlayerControl control = player->getPlayerControl();
1039         lua_newtable(L);
1040         lua_pushboolean(L, control.up);
1041         lua_setfield(L, -2, "up");
1042         lua_pushboolean(L, control.down);
1043         lua_setfield(L, -2, "down");
1044         lua_pushboolean(L, control.left);
1045         lua_setfield(L, -2, "left");
1046         lua_pushboolean(L, control.right);
1047         lua_setfield(L, -2, "right");
1048         lua_pushboolean(L, control.jump);
1049         lua_setfield(L, -2, "jump");
1050         lua_pushboolean(L, control.aux1);
1051         lua_setfield(L, -2, "aux1");
1052         lua_pushboolean(L, control.sneak);
1053         lua_setfield(L, -2, "sneak");
1054         lua_pushboolean(L, control.LMB);
1055         lua_setfield(L, -2, "LMB");
1056         lua_pushboolean(L, control.RMB);
1057         lua_setfield(L, -2, "RMB");
1058         return 1;
1059 }
1060
1061 // get_player_control_bits(self)
1062 int ObjectRef::l_get_player_control_bits(lua_State *L)
1063 {
1064         NO_MAP_LOCK_REQUIRED;
1065         ObjectRef *ref = checkobject(L, 1);
1066         Player *player = getplayer(ref);
1067         if(player == NULL){
1068                 lua_pushlstring(L, "", 0);
1069                 return 1;
1070         }
1071         // Do it
1072         lua_pushnumber(L, player->keyPressed);
1073         return 1;
1074 }
1075
1076 // hud_add(self, form)
1077 int ObjectRef::l_hud_add(lua_State *L)
1078 {
1079         ObjectRef *ref = checkobject(L, 1);
1080         Player *player = getplayer(ref);
1081         if (player == NULL)
1082                 return 0;
1083
1084         HudElement *elem = new HudElement;
1085
1086         elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type",
1087                                                                 es_HudElementType, HUD_ELEM_TEXT);
1088
1089         lua_getfield(L, 2, "position");
1090         elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1091         lua_pop(L, 1);
1092
1093         lua_getfield(L, 2, "scale");
1094         elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1095         lua_pop(L, 1);
1096
1097         lua_getfield(L, 2, "size");
1098         elem->size = lua_istable(L, -1) ? read_v2s32(L, -1) : v2s32();
1099         lua_pop(L, 1);
1100
1101         elem->name   = getstringfield_default(L, 2, "name", "");
1102         elem->text   = getstringfield_default(L, 2, "text", "");
1103         elem->number = getintfield_default(L, 2, "number", 0);
1104         elem->item   = getintfield_default(L, 2, "item", 0);
1105         elem->dir    = getintfield_default(L, 2, "direction", 0);
1106
1107         // Deprecated, only for compatibility's sake
1108         if (elem->dir == 0)
1109                 elem->dir = getintfield_default(L, 2, "dir", 0);
1110
1111         lua_getfield(L, 2, "alignment");
1112         elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1113         lua_pop(L, 1);
1114
1115         lua_getfield(L, 2, "offset");
1116         elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1117         lua_pop(L, 1);
1118
1119         lua_getfield(L, 2, "world_pos");
1120         elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f();
1121         lua_pop(L, 1);
1122
1123         /* check for known deprecated element usage */
1124         if ((elem->type  == HUD_ELEM_STATBAR) && (elem->size == v2s32())) {
1125                 log_deprecated(L,"Deprecated usage of statbar without size!");
1126         }
1127
1128         u32 id = getServer(L)->hudAdd(player, elem);
1129         if (id == (u32)-1) {
1130                 delete elem;
1131                 return 0;
1132         }
1133
1134         lua_pushnumber(L, id);
1135         return 1;
1136 }
1137
1138 // hud_remove(self, id)
1139 int ObjectRef::l_hud_remove(lua_State *L)
1140 {
1141         ObjectRef *ref = checkobject(L, 1);
1142         Player *player = getplayer(ref);
1143         if (player == NULL)
1144                 return 0;
1145
1146         u32 id = -1;
1147         if (!lua_isnil(L, 2))
1148                 id = lua_tonumber(L, 2);
1149
1150         if (!getServer(L)->hudRemove(player, id))
1151                 return 0;
1152
1153         lua_pushboolean(L, true);
1154         return 1;
1155 }
1156
1157 // hud_change(self, id, stat, data)
1158 int ObjectRef::l_hud_change(lua_State *L)
1159 {
1160         ObjectRef *ref = checkobject(L, 1);
1161         Player *player = getplayer(ref);
1162         if (player == NULL)
1163                 return 0;
1164
1165         u32 id = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : -1;
1166
1167         HudElement *e = player->getHud(id);
1168         if (!e)
1169                 return 0;
1170
1171         HudElementStat stat = HUD_STAT_NUMBER;
1172         if (lua_isstring(L, 3)) {
1173                 int statint;
1174                 std::string statstr = lua_tostring(L, 3);
1175                 stat = string_to_enum(es_HudElementStat, statint, statstr) ?
1176                                 (HudElementStat)statint : HUD_STAT_NUMBER;
1177         }
1178
1179         void *value = NULL;
1180         switch (stat) {
1181                 case HUD_STAT_POS:
1182                         e->pos = read_v2f(L, 4);
1183                         value = &e->pos;
1184                         break;
1185                 case HUD_STAT_NAME:
1186                         e->name = luaL_checkstring(L, 4);
1187                         value = &e->name;
1188                         break;
1189                 case HUD_STAT_SCALE:
1190                         e->scale = read_v2f(L, 4);
1191                         value = &e->scale;
1192                         break;
1193                 case HUD_STAT_TEXT:
1194                         e->text = luaL_checkstring(L, 4);
1195                         value = &e->text;
1196                         break;
1197                 case HUD_STAT_NUMBER:
1198                         e->number = luaL_checknumber(L, 4);
1199                         value = &e->number;
1200                         break;
1201                 case HUD_STAT_ITEM:
1202                         e->item = luaL_checknumber(L, 4);
1203                         value = &e->item;
1204                         break;
1205                 case HUD_STAT_DIR:
1206                         e->dir = luaL_checknumber(L, 4);
1207                         value = &e->dir;
1208                         break;
1209                 case HUD_STAT_ALIGN:
1210                         e->align = read_v2f(L, 4);
1211                         value = &e->align;
1212                         break;
1213                 case HUD_STAT_OFFSET:
1214                         e->offset = read_v2f(L, 4);
1215                         value = &e->offset;
1216                         break;
1217                 case HUD_STAT_WORLD_POS:
1218                         e->world_pos = read_v3f(L, 4);
1219                         value = &e->world_pos;
1220                         break;
1221                 case HUD_STAT_SIZE:
1222                         e->size = read_v2s32(L, 4);
1223                         value = &e->size;
1224                         break;
1225         }
1226
1227         getServer(L)->hudChange(player, id, stat, value);
1228
1229         lua_pushboolean(L, true);
1230         return 1;
1231 }
1232
1233 // hud_get(self, id)
1234 int ObjectRef::l_hud_get(lua_State *L)
1235 {
1236         ObjectRef *ref = checkobject(L, 1);
1237         Player *player = getplayer(ref);
1238         if (player == NULL)
1239                 return 0;
1240
1241         u32 id = lua_tonumber(L, -1);
1242
1243         HudElement *e = player->getHud(id);
1244         if (!e)
1245                 return 0;
1246
1247         lua_newtable(L);
1248
1249         lua_pushstring(L, es_HudElementType[(u8)e->type].str);
1250         lua_setfield(L, -2, "type");
1251
1252         push_v2f(L, e->pos);
1253         lua_setfield(L, -2, "position");
1254
1255         lua_pushstring(L, e->name.c_str());
1256         lua_setfield(L, -2, "name");
1257
1258         push_v2f(L, e->scale);
1259         lua_setfield(L, -2, "scale");
1260
1261         lua_pushstring(L, e->text.c_str());
1262         lua_setfield(L, -2, "text");
1263
1264         lua_pushnumber(L, e->number);
1265         lua_setfield(L, -2, "number");
1266
1267         lua_pushnumber(L, e->item);
1268         lua_setfield(L, -2, "item");
1269
1270         lua_pushnumber(L, e->dir);
1271         lua_setfield(L, -2, "direction");
1272
1273         // Deprecated, only for compatibility's sake
1274         lua_pushnumber(L, e->dir);
1275         lua_setfield(L, -2, "dir");
1276
1277         push_v3f(L, e->world_pos);
1278         lua_setfield(L, -2, "world_pos");
1279
1280         return 1;
1281 }
1282
1283 // hud_set_flags(self, flags)
1284 int ObjectRef::l_hud_set_flags(lua_State *L)
1285 {
1286         ObjectRef *ref = checkobject(L, 1);
1287         Player *player = getplayer(ref);
1288         if (player == NULL)
1289                 return 0;
1290
1291         u32 flags = 0;
1292         u32 mask  = 0;
1293         bool flag;
1294
1295         const EnumString *esp = es_HudBuiltinElement;
1296         for (int i = 0; esp[i].str; i++) {
1297                 if (getboolfield(L, 2, esp[i].str, flag)) {
1298                         flags |= esp[i].num * flag;
1299                         mask  |= esp[i].num;
1300                 }
1301         }
1302         if (!getServer(L)->hudSetFlags(player, flags, mask))
1303                 return 0;
1304
1305         lua_pushboolean(L, true);
1306         return 1;
1307 }
1308
1309 int ObjectRef::l_hud_get_flags(lua_State *L)
1310 {
1311         ObjectRef *ref = checkobject(L, 1);
1312         Player *player = getplayer(ref);
1313         if (player == NULL)
1314                 return 0;
1315
1316         lua_newtable(L);
1317         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE);
1318         lua_setfield(L, -2, "hotbar");
1319         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE);
1320         lua_setfield(L, -2, "healthbar");
1321         lua_pushboolean(L, player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE);
1322         lua_setfield(L, -2, "crosshair");
1323         lua_pushboolean(L, player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE);
1324         lua_setfield(L, -2, "wielditem");
1325         lua_pushboolean(L, player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE);
1326         lua_setfield(L, -2, "breathbar");
1327
1328         return 1;
1329 }
1330
1331 // hud_set_hotbar_itemcount(self, hotbar_itemcount)
1332 int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
1333 {
1334         ObjectRef *ref = checkobject(L, 1);
1335         Player *player = getplayer(ref);
1336         if (player == NULL)
1337                 return 0;
1338
1339         s32 hotbar_itemcount = lua_tonumber(L, 2);
1340
1341         if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
1342                 return 0;
1343
1344         lua_pushboolean(L, true);
1345         return 1;
1346 }
1347
1348 // hud_get_hotbar_itemcount(self)
1349 int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
1350 {
1351         ObjectRef *ref = checkobject(L, 1);
1352         Player *player = getplayer(ref);
1353         if (player == NULL)
1354                 return 0;
1355
1356         s32 hotbar_itemcount = getServer(L)->hudGetHotbarItemcount(player);
1357
1358         lua_pushnumber(L, hotbar_itemcount);
1359         return 1;
1360 }
1361
1362 // hud_set_hotbar_image(self, name)
1363 int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
1364 {
1365         ObjectRef *ref = checkobject(L, 1);
1366         Player *player = getplayer(ref);
1367         if (player == NULL)
1368                 return 0;
1369
1370         std::string name = lua_tostring(L, 2);
1371
1372         getServer(L)->hudSetHotbarImage(player, name);
1373         return 1;
1374 }
1375
1376 // hud_get_hotbar_image(self)
1377 int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
1378 {
1379         ObjectRef *ref = checkobject(L, 1);
1380         Player *player = getplayer(ref);
1381         if (player == NULL)
1382                 return 0;
1383
1384         std::string name = getServer(L)->hudGetHotbarImage(player);
1385         lua_pushlstring(L, name.c_str(), name.size());
1386         return 1;
1387 }
1388
1389 // hud_set_hotbar_selected_image(self, name)
1390 int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
1391 {
1392         ObjectRef *ref = checkobject(L, 1);
1393         Player *player = getplayer(ref);
1394         if (player == NULL)
1395                 return 0;
1396
1397         std::string name = lua_tostring(L, 2);
1398
1399         getServer(L)->hudSetHotbarSelectedImage(player, name);
1400         return 1;
1401 }
1402
1403 // hud_get_hotbar_selected_image(self)
1404 int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
1405 {
1406         ObjectRef *ref = checkobject(L, 1);
1407         Player *player = getplayer(ref);
1408         if (player == NULL)
1409                 return 0;
1410
1411         std::string name = getServer(L)->hudGetHotbarSelectedImage(player);
1412         lua_pushlstring(L, name.c_str(), name.size());
1413         return 1;
1414 }
1415
1416 // set_sky(self, bgcolor, type, list)
1417 int ObjectRef::l_set_sky(lua_State *L)
1418 {
1419         ObjectRef *ref = checkobject(L, 1);
1420         Player *player = getplayer(ref);
1421         if (player == NULL)
1422                 return 0;
1423
1424         video::SColor bgcolor(255,255,255,255);
1425         read_color(L, 2, &bgcolor);
1426
1427         std::string type = luaL_checkstring(L, 3);
1428
1429         std::vector<std::string> params;
1430         if (lua_istable(L, 4)) {
1431                 int table = lua_gettop(L);
1432                 lua_pushnil(L);
1433                 while (lua_next(L, table) != 0) {
1434                         // key at index -2 and value at index -1
1435                         if (lua_isstring(L, -1))
1436                                 params.push_back(lua_tostring(L, -1));
1437                         else
1438                                 params.push_back("");
1439                         // removes value, keeps key for next iteration
1440                         lua_pop(L, 1);
1441                 }
1442         }
1443
1444         if (type == "skybox" && params.size() != 6)
1445                 throw LuaError("skybox expects 6 textures");
1446
1447         if (!getServer(L)->setSky(player, bgcolor, type, params))
1448                 return 0;
1449
1450         lua_pushboolean(L, true);
1451         return 1;
1452 }
1453
1454 // get_sky(self)
1455 int ObjectRef::l_get_sky(lua_State *L)
1456 {
1457         ObjectRef *ref = checkobject(L, 1);
1458         Player *player = getplayer(ref);
1459         if (player == NULL)
1460                 return 0;
1461         video::SColor bgcolor(255, 255, 255, 255);
1462         std::string type;
1463         std::vector<std::string> params;
1464
1465         player->getSky(&bgcolor, &type, &params);
1466         type = type == "" ? "regular" : type;
1467
1468         push_ARGB8(L, bgcolor);
1469         lua_pushlstring(L, type.c_str(), type.size());
1470         lua_newtable(L);
1471         s16 i = 1;
1472         for (std::vector<std::string>::iterator it = params.begin();
1473                         it != params.end(); ++it) {
1474                 lua_pushlstring(L, it->c_str(), it->size());
1475                 lua_rawseti(L, -2, i);
1476                 i++;
1477         }
1478         return 3;
1479 }
1480
1481 // override_day_night_ratio(self, brightness=0...1)
1482 int ObjectRef::l_override_day_night_ratio(lua_State *L)
1483 {
1484         ObjectRef *ref = checkobject(L, 1);
1485         Player *player = getplayer(ref);
1486         if (player == NULL)
1487                 return 0;
1488
1489         bool do_override = false;
1490         float ratio = 0.0f;
1491         if (!lua_isnil(L, 2)){
1492                 do_override = true;
1493                 ratio = luaL_checknumber(L, 2);
1494         }
1495
1496         if (!getServer(L)->overrideDayNightRatio(player, do_override, ratio))
1497                 return 0;
1498
1499         lua_pushboolean(L, true);
1500         return 1;
1501 }
1502
1503 // get_day_night_ratio(self)
1504 int ObjectRef::l_get_day_night_ratio(lua_State *L)
1505 {
1506         ObjectRef *ref = checkobject(L, 1);
1507         Player *player = getplayer(ref);
1508         if (player == NULL)
1509                 return 0;
1510
1511         bool do_override;
1512         float ratio;
1513         player->getDayNightRatio(&do_override, &ratio);
1514
1515         if (do_override)
1516                 lua_pushnumber(L, ratio);
1517         else
1518                 lua_pushnil(L);
1519
1520         return 1;
1521 }
1522
1523 // set_nametag_attributes(self, attributes)
1524 int ObjectRef::l_set_nametag_attributes(lua_State *L)
1525 {
1526         NO_MAP_LOCK_REQUIRED;
1527         ObjectRef *ref = checkobject(L, 1);
1528         PlayerSAO *playersao = getplayersao(ref);
1529         if (playersao == NULL)
1530                 return 0;
1531
1532         lua_getfield(L, 2, "color");
1533         if (!lua_isnil(L, -1)) {
1534                 video::SColor color = playersao->getNametagColor();
1535                 if (!read_color(L, -1, &color))
1536                         return 0;
1537                 playersao->setNametagColor(color);
1538         }
1539
1540         lua_pushboolean(L, true);
1541         return 1;
1542 }
1543
1544 // get_nametag_attributes(self)
1545 int ObjectRef::l_get_nametag_attributes(lua_State *L)
1546 {
1547         NO_MAP_LOCK_REQUIRED;
1548         ObjectRef *ref = checkobject(L, 1);
1549         PlayerSAO *playersao = getplayersao(ref);
1550         if (playersao == NULL)
1551                 return 0;
1552
1553         video::SColor color = playersao->getNametagColor();
1554
1555         lua_newtable(L);
1556         push_ARGB8(L, color);
1557         lua_setfield(L, -2, "color");
1558
1559         return 1;
1560 }
1561
1562 ObjectRef::ObjectRef(ServerActiveObject *object):
1563         m_object(object)
1564 {
1565         //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
1566 }
1567
1568 ObjectRef::~ObjectRef()
1569 {
1570         /*if(m_object)
1571                 infostream<<"ObjectRef destructing for id="
1572                                 <<m_object->getId()<<std::endl;
1573         else
1574                 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
1575 }
1576
1577 // Creates an ObjectRef and leaves it on top of stack
1578 // Not callable from Lua; all references are created on the C side.
1579 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
1580 {
1581         ObjectRef *o = new ObjectRef(object);
1582         //infostream<<"ObjectRef::create: o="<<o<<std::endl;
1583         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1584         luaL_getmetatable(L, className);
1585         lua_setmetatable(L, -2);
1586 }
1587
1588 void ObjectRef::set_null(lua_State *L)
1589 {
1590         ObjectRef *o = checkobject(L, -1);
1591         o->m_object = NULL;
1592 }
1593
1594 void ObjectRef::Register(lua_State *L)
1595 {
1596         lua_newtable(L);
1597         int methodtable = lua_gettop(L);
1598         luaL_newmetatable(L, className);
1599         int metatable = lua_gettop(L);
1600
1601         lua_pushliteral(L, "__metatable");
1602         lua_pushvalue(L, methodtable);
1603         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
1604
1605         lua_pushliteral(L, "__index");
1606         lua_pushvalue(L, methodtable);
1607         lua_settable(L, metatable);
1608
1609         lua_pushliteral(L, "__gc");
1610         lua_pushcfunction(L, gc_object);
1611         lua_settable(L, metatable);
1612
1613         lua_pop(L, 1);  // drop metatable
1614
1615         luaL_openlib(L, 0, methods, 0);  // fill methodtable
1616         lua_pop(L, 1);  // drop methodtable
1617
1618         // Cannot be created from Lua
1619         //lua_register(L, className, create_object);
1620 }
1621
1622 const char ObjectRef::className[] = "ObjectRef";
1623 const luaL_reg ObjectRef::methods[] = {
1624         // ServerActiveObject
1625         luamethod(ObjectRef, remove),
1626         luamethod(ObjectRef, getpos),
1627         luamethod(ObjectRef, setpos),
1628         luamethod(ObjectRef, moveto),
1629         luamethod(ObjectRef, punch),
1630         luamethod(ObjectRef, right_click),
1631         luamethod(ObjectRef, set_hp),
1632         luamethod(ObjectRef, get_hp),
1633         luamethod(ObjectRef, get_inventory),
1634         luamethod(ObjectRef, get_wield_list),
1635         luamethod(ObjectRef, get_wield_index),
1636         luamethod(ObjectRef, get_wielded_item),
1637         luamethod(ObjectRef, set_wielded_item),
1638         luamethod(ObjectRef, set_armor_groups),
1639         luamethod(ObjectRef, get_armor_groups),
1640         luamethod(ObjectRef, set_animation),
1641         luamethod(ObjectRef, get_animation),
1642         luamethod(ObjectRef, set_bone_position),
1643         luamethod(ObjectRef, get_bone_position),
1644         luamethod(ObjectRef, set_attach),
1645         luamethod(ObjectRef, get_attach),
1646         luamethod(ObjectRef, set_detach),
1647         luamethod(ObjectRef, set_properties),
1648         luamethod(ObjectRef, get_properties),
1649         // LuaEntitySAO-only
1650         luamethod(ObjectRef, setvelocity),
1651         luamethod(ObjectRef, getvelocity),
1652         luamethod(ObjectRef, setacceleration),
1653         luamethod(ObjectRef, getacceleration),
1654         luamethod(ObjectRef, setyaw),
1655         luamethod(ObjectRef, getyaw),
1656         luamethod(ObjectRef, settexturemod),
1657         luamethod(ObjectRef, setsprite),
1658         luamethod(ObjectRef, get_entity_name),
1659         luamethod(ObjectRef, get_luaentity),
1660         // Player-only
1661         luamethod(ObjectRef, is_player),
1662         luamethod(ObjectRef, is_player_connected),
1663         luamethod(ObjectRef, get_player_name),
1664         luamethod(ObjectRef, get_look_dir),
1665         luamethod(ObjectRef, get_look_pitch),
1666         luamethod(ObjectRef, get_look_yaw),
1667         luamethod(ObjectRef, set_look_yaw),
1668         luamethod(ObjectRef, set_look_pitch),
1669         luamethod(ObjectRef, get_breath),
1670         luamethod(ObjectRef, set_breath),
1671         luamethod(ObjectRef, set_inventory_formspec),
1672         luamethod(ObjectRef, get_inventory_formspec),
1673         luamethod(ObjectRef, get_player_control),
1674         luamethod(ObjectRef, get_player_control_bits),
1675         luamethod(ObjectRef, set_physics_override),
1676         luamethod(ObjectRef, get_physics_override),
1677         luamethod(ObjectRef, hud_add),
1678         luamethod(ObjectRef, hud_remove),
1679         luamethod(ObjectRef, hud_change),
1680         luamethod(ObjectRef, hud_get),
1681         luamethod(ObjectRef, hud_set_flags),
1682         luamethod(ObjectRef, hud_get_flags),
1683         luamethod(ObjectRef, hud_set_hotbar_itemcount),
1684         luamethod(ObjectRef, hud_get_hotbar_itemcount),
1685         luamethod(ObjectRef, hud_set_hotbar_image),
1686         luamethod(ObjectRef, hud_get_hotbar_image),
1687         luamethod(ObjectRef, hud_set_hotbar_selected_image),
1688         luamethod(ObjectRef, hud_get_hotbar_selected_image),
1689         luamethod(ObjectRef, set_sky),
1690         luamethod(ObjectRef, get_sky),
1691         luamethod(ObjectRef, override_day_night_ratio),
1692         luamethod(ObjectRef, get_day_night_ratio),
1693         luamethod(ObjectRef, set_local_animation),
1694         luamethod(ObjectRef, get_local_animation),
1695         luamethod(ObjectRef, set_eye_offset),
1696         luamethod(ObjectRef, get_eye_offset),
1697         luamethod(ObjectRef, set_nametag_attributes),
1698         luamethod(ObjectRef, get_nametag_attributes),
1699         {0,0}
1700 };