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