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