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