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