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