Add protocol_version and supported package types to ContentDB urls
[oweals/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 <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_yaw(self, radians)
893 int ObjectRef::l_set_yaw(lua_State *L)
894 {
895         NO_MAP_LOCK_REQUIRED;
896         ObjectRef *ref = checkobject(L, 1);
897         LuaEntitySAO *co = getluaobject(ref);
898         if (co == NULL) return 0;
899         if (isNaN(L, 2))
900                 throw LuaError("ObjectRef::set_yaw: NaN value is not allowed.");
901
902         float yaw = readParam<float>(L, 2) * core::RADTODEG;
903         // Do it
904         co->setYaw(yaw);
905         return 0;
906 }
907
908 // get_yaw(self)
909 int ObjectRef::l_get_yaw(lua_State *L)
910 {
911         NO_MAP_LOCK_REQUIRED;
912         ObjectRef *ref = checkobject(L, 1);
913         LuaEntitySAO *co = getluaobject(ref);
914         if (co == NULL) return 0;
915         // Do it
916         float yaw = co->getYaw() * core::DEGTORAD;
917         lua_pushnumber(L, yaw);
918         return 1;
919 }
920
921 // set_texture_mod(self, mod)
922 int ObjectRef::l_set_texture_mod(lua_State *L)
923 {
924         NO_MAP_LOCK_REQUIRED;
925         ObjectRef *ref = checkobject(L, 1);
926         LuaEntitySAO *co = getluaobject(ref);
927         if (co == NULL) return 0;
928         // Do it
929         std::string mod = luaL_checkstring(L, 2);
930         co->setTextureMod(mod);
931         return 0;
932 }
933
934 // get_texture_mod(self)
935 int ObjectRef::l_get_texture_mod(lua_State *L)
936 {
937         NO_MAP_LOCK_REQUIRED;
938         ObjectRef *ref = checkobject(L, 1);
939         LuaEntitySAO *co = getluaobject(ref);
940         if (co == NULL) return 0;
941         // Do it
942         std::string mod = co->getTextureMod();
943         lua_pushstring(L, mod.c_str());
944         return 1;
945 }
946
947 // set_sprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
948 //           select_horiz_by_yawpitch=false)
949 int ObjectRef::l_set_sprite(lua_State *L)
950 {
951         NO_MAP_LOCK_REQUIRED;
952         ObjectRef *ref = checkobject(L, 1);
953         LuaEntitySAO *co = getluaobject(ref);
954         if (co == NULL) return 0;
955         // Do it
956         v2s16 p(0,0);
957         if (!lua_isnil(L, 2))
958                 p = readParam<v2s16>(L, 2);
959         int num_frames = 1;
960         if (!lua_isnil(L, 3))
961                 num_frames = lua_tonumber(L, 3);
962         float framelength = 0.2;
963         if (!lua_isnil(L, 4))
964                 framelength = lua_tonumber(L, 4);
965         bool select_horiz_by_yawpitch = false;
966         if (!lua_isnil(L, 5))
967                 select_horiz_by_yawpitch = readParam<bool>(L, 5);
968         co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
969         return 0;
970 }
971
972 // DEPRECATED
973 // get_entity_name(self)
974 int ObjectRef::l_get_entity_name(lua_State *L)
975 {
976         NO_MAP_LOCK_REQUIRED;
977         ObjectRef *ref = checkobject(L, 1);
978         LuaEntitySAO *co = getluaobject(ref);
979         log_deprecated(L,"Deprecated call to \"get_entity_name");
980         if (co == NULL) return 0;
981         // Do it
982         std::string name = co->getName();
983         lua_pushstring(L, name.c_str());
984         return 1;
985 }
986
987 // get_luaentity(self)
988 int ObjectRef::l_get_luaentity(lua_State *L)
989 {
990         NO_MAP_LOCK_REQUIRED;
991         ObjectRef *ref = checkobject(L, 1);
992         LuaEntitySAO *co = getluaobject(ref);
993         if (co == NULL) return 0;
994         // Do it
995         luaentity_get(L, co->getId());
996         return 1;
997 }
998
999 /* Player-only */
1000
1001 // is_player_connected(self)
1002 int ObjectRef::l_is_player_connected(lua_State *L)
1003 {
1004         NO_MAP_LOCK_REQUIRED;
1005         ObjectRef *ref = checkobject(L, 1);
1006         RemotePlayer *player = getplayer(ref);
1007         lua_pushboolean(L, (player != NULL && player->getPeerId() != PEER_ID_INEXISTENT));
1008         return 1;
1009 }
1010
1011 // get_player_name(self)
1012 int ObjectRef::l_get_player_name(lua_State *L)
1013 {
1014         NO_MAP_LOCK_REQUIRED;
1015         ObjectRef *ref = checkobject(L, 1);
1016         RemotePlayer *player = getplayer(ref);
1017         if (player == NULL) {
1018                 lua_pushlstring(L, "", 0);
1019                 return 1;
1020         }
1021         // Do it
1022         lua_pushstring(L, player->getName());
1023         return 1;
1024 }
1025
1026 // get_player_velocity(self)
1027 int ObjectRef::l_get_player_velocity(lua_State *L)
1028 {
1029         NO_MAP_LOCK_REQUIRED;
1030         ObjectRef *ref = checkobject(L, 1);
1031         RemotePlayer *player = getplayer(ref);
1032         if (player == NULL) {
1033                 lua_pushnil(L);
1034                 return 1;
1035         }
1036         // Do it
1037         push_v3f(L, player->getSpeed() / BS);
1038         return 1;
1039 }
1040
1041 // get_look_dir(self)
1042 int ObjectRef::l_get_look_dir(lua_State *L)
1043 {
1044         NO_MAP_LOCK_REQUIRED;
1045         ObjectRef *ref = checkobject(L, 1);
1046         PlayerSAO* co = getplayersao(ref);
1047         if (co == NULL) return 0;
1048         // Do it
1049         float pitch = co->getRadPitchDep();
1050         float yaw = co->getRadYawDep();
1051         v3f v(std::cos(pitch) * std::cos(yaw), std::sin(pitch), std::cos(pitch) *
1052                 std::sin(yaw));
1053         push_v3f(L, v);
1054         return 1;
1055 }
1056
1057 // DEPRECATED
1058 // get_look_pitch(self)
1059 int ObjectRef::l_get_look_pitch(lua_State *L)
1060 {
1061         NO_MAP_LOCK_REQUIRED;
1062
1063         log_deprecated(L,
1064                 "Deprecated call to get_look_pitch, use get_look_vertical instead");
1065
1066         ObjectRef *ref = checkobject(L, 1);
1067         PlayerSAO* co = getplayersao(ref);
1068         if (co == NULL) return 0;
1069         // Do it
1070         lua_pushnumber(L, co->getRadPitchDep());
1071         return 1;
1072 }
1073
1074 // DEPRECATED
1075 // get_look_yaw(self)
1076 int ObjectRef::l_get_look_yaw(lua_State *L)
1077 {
1078         NO_MAP_LOCK_REQUIRED;
1079
1080         log_deprecated(L,
1081                 "Deprecated call to get_look_yaw, use get_look_horizontal instead");
1082
1083         ObjectRef *ref = checkobject(L, 1);
1084         PlayerSAO* co = getplayersao(ref);
1085         if (co == NULL) return 0;
1086         // Do it
1087         lua_pushnumber(L, co->getRadYawDep());
1088         return 1;
1089 }
1090
1091 // get_look_pitch2(self)
1092 int ObjectRef::l_get_look_vertical(lua_State *L)
1093 {
1094         NO_MAP_LOCK_REQUIRED;
1095         ObjectRef *ref = checkobject(L, 1);
1096         PlayerSAO* co = getplayersao(ref);
1097         if (co == NULL) return 0;
1098         // Do it
1099         lua_pushnumber(L, co->getRadPitch());
1100         return 1;
1101 }
1102
1103 // get_look_yaw2(self)
1104 int ObjectRef::l_get_look_horizontal(lua_State *L)
1105 {
1106         NO_MAP_LOCK_REQUIRED;
1107         ObjectRef *ref = checkobject(L, 1);
1108         PlayerSAO* co = getplayersao(ref);
1109         if (co == NULL) return 0;
1110         // Do it
1111         lua_pushnumber(L, co->getRadYaw());
1112         return 1;
1113 }
1114
1115 // set_look_vertical(self, radians)
1116 int ObjectRef::l_set_look_vertical(lua_State *L)
1117 {
1118         NO_MAP_LOCK_REQUIRED;
1119         ObjectRef *ref = checkobject(L, 1);
1120         PlayerSAO* co = getplayersao(ref);
1121         if (co == NULL) return 0;
1122         float pitch = readParam<float>(L, 2) * core::RADTODEG;
1123         // Do it
1124         co->setPitchAndSend(pitch);
1125         return 1;
1126 }
1127
1128 // set_look_horizontal(self, radians)
1129 int ObjectRef::l_set_look_horizontal(lua_State *L)
1130 {
1131         NO_MAP_LOCK_REQUIRED;
1132         ObjectRef *ref = checkobject(L, 1);
1133         PlayerSAO* co = getplayersao(ref);
1134         if (co == NULL) return 0;
1135         float yaw = readParam<float>(L, 2) * core::RADTODEG;
1136         // Do it
1137         co->setYawAndSend(yaw);
1138         return 1;
1139 }
1140
1141 // DEPRECATED
1142 // set_look_pitch(self, radians)
1143 int ObjectRef::l_set_look_pitch(lua_State *L)
1144 {
1145         NO_MAP_LOCK_REQUIRED;
1146
1147         log_deprecated(L,
1148                 "Deprecated call to set_look_pitch, use set_look_vertical instead.");
1149
1150         ObjectRef *ref = checkobject(L, 1);
1151         PlayerSAO* co = getplayersao(ref);
1152         if (co == NULL) return 0;
1153         float pitch = readParam<float>(L, 2) * core::RADTODEG;
1154         // Do it
1155         co->setPitchAndSend(pitch);
1156         return 1;
1157 }
1158
1159 // DEPRECATED
1160 // set_look_yaw(self, radians)
1161 int ObjectRef::l_set_look_yaw(lua_State *L)
1162 {
1163         NO_MAP_LOCK_REQUIRED;
1164
1165         log_deprecated(L,
1166                 "Deprecated call to set_look_yaw, use set_look_horizontal instead.");
1167
1168         ObjectRef *ref = checkobject(L, 1);
1169         PlayerSAO* co = getplayersao(ref);
1170         if (co == NULL) return 0;
1171         float yaw = readParam<float>(L, 2) * core::RADTODEG;
1172         // Do it
1173         co->setYawAndSend(yaw);
1174         return 1;
1175 }
1176
1177 // set_breath(self, breath)
1178 int ObjectRef::l_set_breath(lua_State *L)
1179 {
1180         NO_MAP_LOCK_REQUIRED;
1181         ObjectRef *ref = checkobject(L, 1);
1182         PlayerSAO* co = getplayersao(ref);
1183         if (co == NULL) return 0;
1184         u16 breath = luaL_checknumber(L, 2);
1185         co->setBreath(breath);
1186
1187         return 0;
1188 }
1189
1190 // get_breath(self)
1191 int ObjectRef::l_get_breath(lua_State *L)
1192 {
1193         NO_MAP_LOCK_REQUIRED;
1194         ObjectRef *ref = checkobject(L, 1);
1195         PlayerSAO* co = getplayersao(ref);
1196         if (co == NULL) return 0;
1197         // Do it
1198         u16 breath = co->getBreath();
1199         lua_pushinteger (L, breath);
1200         return 1;
1201 }
1202
1203 // set_attribute(self, attribute, value)
1204 int ObjectRef::l_set_attribute(lua_State *L)
1205 {
1206         ObjectRef *ref = checkobject(L, 1);
1207         PlayerSAO* co = getplayersao(ref);
1208         if (co == NULL)
1209                 return 0;
1210
1211         std::string attr = luaL_checkstring(L, 2);
1212         if (lua_isnil(L, 3)) {
1213                 co->getMeta().removeString(attr);
1214         } else {
1215                 std::string value = luaL_checkstring(L, 3);
1216                 co->getMeta().setString(attr, value);
1217         }
1218         return 1;
1219 }
1220
1221 // get_attribute(self, attribute)
1222 int ObjectRef::l_get_attribute(lua_State *L)
1223 {
1224         ObjectRef *ref = checkobject(L, 1);
1225         PlayerSAO* co = getplayersao(ref);
1226         if (co == NULL)
1227                 return 0;
1228
1229         std::string attr = luaL_checkstring(L, 2);
1230
1231         std::string value;
1232         if (co->getMeta().getStringToRef(attr, value)) {
1233                 lua_pushstring(L, value.c_str());
1234                 return 1;
1235         }
1236
1237         return 0;
1238 }
1239
1240
1241 // get_meta(self, attribute)
1242 int ObjectRef::l_get_meta(lua_State *L)
1243 {
1244         ObjectRef *ref = checkobject(L, 1);
1245         PlayerSAO *co = getplayersao(ref);
1246         if (co == NULL)
1247                 return 0;
1248
1249         PlayerMetaRef::create(L, &co->getMeta());
1250         return 1;
1251 }
1252
1253
1254 // set_inventory_formspec(self, formspec)
1255 int ObjectRef::l_set_inventory_formspec(lua_State *L)
1256 {
1257         NO_MAP_LOCK_REQUIRED;
1258         ObjectRef *ref = checkobject(L, 1);
1259         RemotePlayer *player = getplayer(ref);
1260         if (player == NULL) return 0;
1261         std::string formspec = luaL_checkstring(L, 2);
1262
1263         player->inventory_formspec = formspec;
1264         getServer(L)->reportInventoryFormspecModified(player->getName());
1265         lua_pushboolean(L, true);
1266         return 1;
1267 }
1268
1269 // get_inventory_formspec(self) -> formspec
1270 int ObjectRef::l_get_inventory_formspec(lua_State *L)
1271 {
1272         NO_MAP_LOCK_REQUIRED;
1273         ObjectRef *ref = checkobject(L, 1);
1274         RemotePlayer *player = getplayer(ref);
1275         if (player == NULL) return 0;
1276
1277         std::string formspec = player->inventory_formspec;
1278         lua_pushlstring(L, formspec.c_str(), formspec.size());
1279         return 1;
1280 }
1281
1282 // set_formspec_prepend(self, formspec)
1283 int ObjectRef::l_set_formspec_prepend(lua_State *L)
1284 {
1285         NO_MAP_LOCK_REQUIRED;
1286         ObjectRef *ref = checkobject(L, 1);
1287         RemotePlayer *player = getplayer(ref);
1288         if (player == NULL)
1289                 return 0;
1290
1291         std::string formspec = luaL_checkstring(L, 2);
1292
1293         player->formspec_prepend = formspec;
1294         getServer(L)->reportFormspecPrependModified(player->getName());
1295         lua_pushboolean(L, true);
1296         return 1;
1297 }
1298
1299 // get_formspec_prepend(self) -> formspec
1300 int ObjectRef::l_get_formspec_prepend(lua_State *L)
1301 {
1302         NO_MAP_LOCK_REQUIRED;
1303         ObjectRef *ref = checkobject(L, 1);
1304         RemotePlayer *player = getplayer(ref);
1305         if (player == NULL)
1306                  return 0;
1307
1308         std::string formspec = player->formspec_prepend;
1309         lua_pushlstring(L, formspec.c_str(), formspec.size());
1310         return 1;
1311 }
1312
1313 // get_player_control(self)
1314 int ObjectRef::l_get_player_control(lua_State *L)
1315 {
1316         NO_MAP_LOCK_REQUIRED;
1317         ObjectRef *ref = checkobject(L, 1);
1318         RemotePlayer *player = getplayer(ref);
1319         if (player == NULL) {
1320                 lua_pushlstring(L, "", 0);
1321                 return 1;
1322         }
1323
1324         const PlayerControl &control = player->getPlayerControl();
1325         lua_newtable(L);
1326         lua_pushboolean(L, control.up);
1327         lua_setfield(L, -2, "up");
1328         lua_pushboolean(L, control.down);
1329         lua_setfield(L, -2, "down");
1330         lua_pushboolean(L, control.left);
1331         lua_setfield(L, -2, "left");
1332         lua_pushboolean(L, control.right);
1333         lua_setfield(L, -2, "right");
1334         lua_pushboolean(L, control.jump);
1335         lua_setfield(L, -2, "jump");
1336         lua_pushboolean(L, control.aux1);
1337         lua_setfield(L, -2, "aux1");
1338         lua_pushboolean(L, control.sneak);
1339         lua_setfield(L, -2, "sneak");
1340         lua_pushboolean(L, control.LMB);
1341         lua_setfield(L, -2, "LMB");
1342         lua_pushboolean(L, control.RMB);
1343         lua_setfield(L, -2, "RMB");
1344         return 1;
1345 }
1346
1347 // get_player_control_bits(self)
1348 int ObjectRef::l_get_player_control_bits(lua_State *L)
1349 {
1350         NO_MAP_LOCK_REQUIRED;
1351         ObjectRef *ref = checkobject(L, 1);
1352         RemotePlayer *player = getplayer(ref);
1353         if (player == NULL) {
1354                 lua_pushlstring(L, "", 0);
1355                 return 1;
1356         }
1357         // Do it
1358         lua_pushnumber(L, player->keyPressed);
1359         return 1;
1360 }
1361
1362 // hud_add(self, form)
1363 int ObjectRef::l_hud_add(lua_State *L)
1364 {
1365         NO_MAP_LOCK_REQUIRED;
1366         ObjectRef *ref = checkobject(L, 1);
1367         RemotePlayer *player = getplayer(ref);
1368         if (player == NULL)
1369                 return 0;
1370
1371         HudElement *elem = new HudElement;
1372         read_hud_element(L, elem);
1373
1374         u32 id = getServer(L)->hudAdd(player, elem);
1375         if (id == U32_MAX) {
1376                 delete elem;
1377                 return 0;
1378         }
1379
1380         lua_pushnumber(L, id);
1381         return 1;
1382 }
1383
1384 // hud_remove(self, id)
1385 int ObjectRef::l_hud_remove(lua_State *L)
1386 {
1387         NO_MAP_LOCK_REQUIRED;
1388         ObjectRef *ref = checkobject(L, 1);
1389         RemotePlayer *player = getplayer(ref);
1390         if (player == NULL)
1391                 return 0;
1392
1393         u32 id = -1;
1394         if (!lua_isnil(L, 2))
1395                 id = lua_tonumber(L, 2);
1396
1397         if (!getServer(L)->hudRemove(player, id))
1398                 return 0;
1399
1400         lua_pushboolean(L, true);
1401         return 1;
1402 }
1403
1404 // hud_change(self, id, stat, data)
1405 int ObjectRef::l_hud_change(lua_State *L)
1406 {
1407         NO_MAP_LOCK_REQUIRED;
1408         ObjectRef *ref = checkobject(L, 1);
1409         RemotePlayer *player = getplayer(ref);
1410         if (player == NULL)
1411                 return 0;
1412
1413         u32 id = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : -1;
1414
1415         HudElement *e = player->getHud(id);
1416         if (!e)
1417                 return 0;
1418
1419         void *value = NULL;
1420         HudElementStat stat = read_hud_change(L, e, &value);
1421
1422         getServer(L)->hudChange(player, id, stat, value);
1423
1424         lua_pushboolean(L, true);
1425         return 1;
1426 }
1427
1428 // hud_get(self, id)
1429 int ObjectRef::l_hud_get(lua_State *L)
1430 {
1431         NO_MAP_LOCK_REQUIRED;
1432         ObjectRef *ref = checkobject(L, 1);
1433         RemotePlayer *player = getplayer(ref);
1434         if (player == NULL)
1435                 return 0;
1436
1437         u32 id = lua_tonumber(L, -1);
1438
1439         HudElement *e = player->getHud(id);
1440         if (!e)
1441                 return 0;
1442         push_hud_element(L, e);
1443         return 1;
1444 }
1445
1446 // hud_set_flags(self, flags)
1447 int ObjectRef::l_hud_set_flags(lua_State *L)
1448 {
1449         NO_MAP_LOCK_REQUIRED;
1450         ObjectRef *ref = checkobject(L, 1);
1451         RemotePlayer *player = getplayer(ref);
1452         if (player == NULL)
1453                 return 0;
1454
1455         u32 flags = 0;
1456         u32 mask  = 0;
1457         bool flag;
1458
1459         const EnumString *esp = es_HudBuiltinElement;
1460         for (int i = 0; esp[i].str; i++) {
1461                 if (getboolfield(L, 2, esp[i].str, flag)) {
1462                         flags |= esp[i].num * flag;
1463                         mask  |= esp[i].num;
1464                 }
1465         }
1466         if (!getServer(L)->hudSetFlags(player, flags, mask))
1467                 return 0;
1468
1469         lua_pushboolean(L, true);
1470         return 1;
1471 }
1472
1473 int ObjectRef::l_hud_get_flags(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         lua_newtable(L);
1482         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE);
1483         lua_setfield(L, -2, "hotbar");
1484         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE);
1485         lua_setfield(L, -2, "healthbar");
1486         lua_pushboolean(L, player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE);
1487         lua_setfield(L, -2, "crosshair");
1488         lua_pushboolean(L, player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE);
1489         lua_setfield(L, -2, "wielditem");
1490         lua_pushboolean(L, player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE);
1491         lua_setfield(L, -2, "breathbar");
1492         lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
1493         lua_setfield(L, -2, "minimap");
1494         lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE);
1495         lua_setfield(L, -2, "minimap_radar");
1496
1497         return 1;
1498 }
1499
1500 // hud_set_hotbar_itemcount(self, hotbar_itemcount)
1501 int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
1502 {
1503         NO_MAP_LOCK_REQUIRED;
1504         ObjectRef *ref = checkobject(L, 1);
1505         RemotePlayer *player = getplayer(ref);
1506         if (player == NULL)
1507                 return 0;
1508
1509         s32 hotbar_itemcount = lua_tonumber(L, 2);
1510
1511         if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
1512                 return 0;
1513
1514         lua_pushboolean(L, true);
1515         return 1;
1516 }
1517
1518 // hud_get_hotbar_itemcount(self)
1519 int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
1520 {
1521         NO_MAP_LOCK_REQUIRED;
1522         ObjectRef *ref = checkobject(L, 1);
1523         RemotePlayer *player = getplayer(ref);
1524         if (player == NULL)
1525                 return 0;
1526
1527         lua_pushnumber(L, player->getHotbarItemcount());
1528         return 1;
1529 }
1530
1531 // hud_set_hotbar_image(self, name)
1532 int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
1533 {
1534         NO_MAP_LOCK_REQUIRED;
1535         ObjectRef *ref = checkobject(L, 1);
1536         RemotePlayer *player = getplayer(ref);
1537         if (player == NULL)
1538                 return 0;
1539
1540         std::string name = readParam<std::string>(L, 2);
1541
1542         getServer(L)->hudSetHotbarImage(player, name);
1543         return 1;
1544 }
1545
1546 // hud_get_hotbar_image(self)
1547 int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
1548 {
1549         NO_MAP_LOCK_REQUIRED;
1550         ObjectRef *ref = checkobject(L, 1);
1551         RemotePlayer *player = getplayer(ref);
1552         if (player == NULL)
1553                 return 0;
1554
1555         const std::string &name = player->getHotbarImage();
1556         lua_pushlstring(L, name.c_str(), name.size());
1557         return 1;
1558 }
1559
1560 // hud_set_hotbar_selected_image(self, name)
1561 int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
1562 {
1563         NO_MAP_LOCK_REQUIRED;
1564         ObjectRef *ref = checkobject(L, 1);
1565         RemotePlayer *player = getplayer(ref);
1566         if (player == NULL)
1567                 return 0;
1568
1569         std::string name = readParam<std::string>(L, 2);
1570
1571         getServer(L)->hudSetHotbarSelectedImage(player, name);
1572         return 1;
1573 }
1574
1575 // hud_get_hotbar_selected_image(self)
1576 int ObjectRef::l_hud_get_hotbar_selected_image(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         const std::string &name = player->getHotbarSelectedImage();
1585         lua_pushlstring(L, name.c_str(), name.size());
1586         return 1;
1587 }
1588
1589 // set_sky(self, bgcolor, type, list, clouds = true)
1590 int ObjectRef::l_set_sky(lua_State *L)
1591 {
1592         NO_MAP_LOCK_REQUIRED;
1593         ObjectRef *ref = checkobject(L, 1);
1594         RemotePlayer *player = getplayer(ref);
1595         if (player == NULL)
1596                 return 0;
1597
1598         video::SColor bgcolor(255,255,255,255);
1599         read_color(L, 2, &bgcolor);
1600
1601         std::string type = luaL_checkstring(L, 3);
1602
1603         std::vector<std::string> params;
1604         if (lua_istable(L, 4)) {
1605                 lua_pushnil(L);
1606                 while (lua_next(L, 4) != 0) {
1607                         // key at index -2 and value at index -1
1608                         if (lua_isstring(L, -1))
1609                                 params.emplace_back(readParam<std::string>(L, -1));
1610                         else
1611                                 params.emplace_back("");
1612                         // removes value, keeps key for next iteration
1613                         lua_pop(L, 1);
1614                 }
1615         }
1616
1617         if (type == "skybox" && params.size() != 6)
1618                 throw LuaError("skybox expects 6 textures");
1619
1620         bool clouds = true;
1621         if (lua_isboolean(L, 5))
1622                 clouds = readParam<bool>(L, 5);
1623
1624         getServer(L)->setSky(player, bgcolor, type, params, clouds);
1625         lua_pushboolean(L, true);
1626         return 1;
1627 }
1628
1629 // get_sky(self)
1630 int ObjectRef::l_get_sky(lua_State *L)
1631 {
1632         NO_MAP_LOCK_REQUIRED;
1633         ObjectRef *ref = checkobject(L, 1);
1634         RemotePlayer *player = getplayer(ref);
1635         if (player == NULL)
1636                 return 0;
1637         video::SColor bgcolor(255, 255, 255, 255);
1638         std::string type;
1639         std::vector<std::string> params;
1640         bool clouds;
1641
1642         player->getSky(&bgcolor, &type, &params, &clouds);
1643         type = type.empty() ? "regular" : type;
1644
1645         push_ARGB8(L, bgcolor);
1646         lua_pushlstring(L, type.c_str(), type.size());
1647         lua_newtable(L);
1648         s16 i = 1;
1649         for (const std::string &param : params) {
1650                 lua_pushlstring(L, param.c_str(), param.size());
1651                 lua_rawseti(L, -2, i);
1652                 i++;
1653         }
1654         lua_pushboolean(L, clouds);
1655         return 4;
1656 }
1657
1658 // set_clouds(self, {density=, color=, ambient=, height=, thickness=, speed=})
1659 int ObjectRef::l_set_clouds(lua_State *L)
1660 {
1661         NO_MAP_LOCK_REQUIRED;
1662         ObjectRef *ref = checkobject(L, 1);
1663         RemotePlayer *player = getplayer(ref);
1664         if (!player)
1665                 return 0;
1666         if (!lua_istable(L, 2))
1667                 return 0;
1668
1669         CloudParams cloud_params = player->getCloudParams();
1670
1671         cloud_params.density = getfloatfield_default(L, 2, "density", cloud_params.density);
1672
1673         lua_getfield(L, 2, "color");
1674         if (!lua_isnil(L, -1))
1675                 read_color(L, -1, &cloud_params.color_bright);
1676         lua_pop(L, 1);
1677         lua_getfield(L, 2, "ambient");
1678         if (!lua_isnil(L, -1))
1679                 read_color(L, -1, &cloud_params.color_ambient);
1680         lua_pop(L, 1);
1681
1682         cloud_params.height    = getfloatfield_default(L, 2, "height",    cloud_params.height   );
1683         cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness);
1684
1685         lua_getfield(L, 2, "speed");
1686         if (lua_istable(L, -1)) {
1687                 v2f new_speed;
1688                 new_speed.X = getfloatfield_default(L, -1, "x", 0);
1689                 new_speed.Y = getfloatfield_default(L, -1, "z", 0);
1690                 cloud_params.speed = new_speed;
1691         }
1692         lua_pop(L, 1);
1693
1694         getServer(L)->setClouds(player, cloud_params);
1695         lua_pushboolean(L, true);
1696         return 1;
1697 }
1698
1699 int ObjectRef::l_get_clouds(lua_State *L)
1700 {
1701         NO_MAP_LOCK_REQUIRED;
1702         ObjectRef *ref = checkobject(L, 1);
1703         RemotePlayer *player = getplayer(ref);
1704         if (!player)
1705                 return 0;
1706         const CloudParams &cloud_params = player->getCloudParams();
1707
1708         lua_newtable(L);
1709         lua_pushnumber(L, cloud_params.density);
1710         lua_setfield(L, -2, "density");
1711         push_ARGB8(L, cloud_params.color_bright);
1712         lua_setfield(L, -2, "color");
1713         push_ARGB8(L, cloud_params.color_ambient);
1714         lua_setfield(L, -2, "ambient");
1715         lua_pushnumber(L, cloud_params.height);
1716         lua_setfield(L, -2, "height");
1717         lua_pushnumber(L, cloud_params.thickness);
1718         lua_setfield(L, -2, "thickness");
1719         lua_newtable(L);
1720         lua_pushnumber(L, cloud_params.speed.X);
1721         lua_setfield(L, -2, "x");
1722         lua_pushnumber(L, cloud_params.speed.Y);
1723         lua_setfield(L, -2, "y");
1724         lua_setfield(L, -2, "speed");
1725
1726         return 1;
1727 }
1728
1729
1730 // override_day_night_ratio(self, brightness=0...1)
1731 int ObjectRef::l_override_day_night_ratio(lua_State *L)
1732 {
1733         NO_MAP_LOCK_REQUIRED;
1734         ObjectRef *ref = checkobject(L, 1);
1735         RemotePlayer *player = getplayer(ref);
1736         if (player == NULL)
1737                 return 0;
1738
1739         bool do_override = false;
1740         float ratio = 0.0f;
1741         if (!lua_isnil(L, 2)) {
1742                 do_override = true;
1743                 ratio = readParam<float>(L, 2);
1744         }
1745
1746         if (!getServer(L)->overrideDayNightRatio(player, do_override, ratio))
1747                 return 0;
1748
1749         lua_pushboolean(L, true);
1750         return 1;
1751 }
1752
1753 // get_day_night_ratio(self)
1754 int ObjectRef::l_get_day_night_ratio(lua_State *L)
1755 {
1756         NO_MAP_LOCK_REQUIRED;
1757         ObjectRef *ref = checkobject(L, 1);
1758         RemotePlayer *player = getplayer(ref);
1759         if (player == NULL)
1760                 return 0;
1761
1762         bool do_override;
1763         float ratio;
1764         player->getDayNightRatio(&do_override, &ratio);
1765
1766         if (do_override)
1767                 lua_pushnumber(L, ratio);
1768         else
1769                 lua_pushnil(L);
1770
1771         return 1;
1772 }
1773
1774 ObjectRef::ObjectRef(ServerActiveObject *object):
1775         m_object(object)
1776 {
1777         //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
1778 }
1779
1780 // Creates an ObjectRef and leaves it on top of stack
1781 // Not callable from Lua; all references are created on the C side.
1782 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
1783 {
1784         ObjectRef *o = new ObjectRef(object);
1785         //infostream<<"ObjectRef::create: o="<<o<<std::endl;
1786         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1787         luaL_getmetatable(L, className);
1788         lua_setmetatable(L, -2);
1789 }
1790
1791 void ObjectRef::set_null(lua_State *L)
1792 {
1793         ObjectRef *o = checkobject(L, -1);
1794         o->m_object = NULL;
1795 }
1796
1797 void ObjectRef::Register(lua_State *L)
1798 {
1799         lua_newtable(L);
1800         int methodtable = lua_gettop(L);
1801         luaL_newmetatable(L, className);
1802         int metatable = lua_gettop(L);
1803
1804         lua_pushliteral(L, "__metatable");
1805         lua_pushvalue(L, methodtable);
1806         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
1807
1808         lua_pushliteral(L, "__index");
1809         lua_pushvalue(L, methodtable);
1810         lua_settable(L, metatable);
1811
1812         lua_pushliteral(L, "__gc");
1813         lua_pushcfunction(L, gc_object);
1814         lua_settable(L, metatable);
1815
1816         lua_pop(L, 1);  // drop metatable
1817
1818         markAliasDeprecated(methods);
1819         luaL_openlib(L, 0, methods, 0);  // fill methodtable
1820         lua_pop(L, 1);  // drop methodtable
1821
1822         // Cannot be created from Lua
1823         //lua_register(L, className, create_object);
1824 }
1825
1826 const char ObjectRef::className[] = "ObjectRef";
1827 luaL_Reg ObjectRef::methods[] = {
1828         // ServerActiveObject
1829         luamethod(ObjectRef, remove),
1830         luamethod_aliased(ObjectRef, get_pos, getpos),
1831         luamethod_aliased(ObjectRef, set_pos, setpos),
1832         luamethod_aliased(ObjectRef, move_to, moveto),
1833         luamethod(ObjectRef, punch),
1834         luamethod(ObjectRef, right_click),
1835         luamethod(ObjectRef, set_hp),
1836         luamethod(ObjectRef, get_hp),
1837         luamethod(ObjectRef, get_inventory),
1838         luamethod(ObjectRef, get_wield_list),
1839         luamethod(ObjectRef, get_wield_index),
1840         luamethod(ObjectRef, get_wielded_item),
1841         luamethod(ObjectRef, set_wielded_item),
1842         luamethod(ObjectRef, set_armor_groups),
1843         luamethod(ObjectRef, get_armor_groups),
1844         luamethod(ObjectRef, set_animation),
1845         luamethod(ObjectRef, get_animation),
1846         luamethod(ObjectRef, set_animation_frame_speed),
1847         luamethod(ObjectRef, set_bone_position),
1848         luamethod(ObjectRef, get_bone_position),
1849         luamethod(ObjectRef, set_attach),
1850         luamethod(ObjectRef, get_attach),
1851         luamethod(ObjectRef, set_detach),
1852         luamethod(ObjectRef, set_properties),
1853         luamethod(ObjectRef, get_properties),
1854         luamethod(ObjectRef, set_nametag_attributes),
1855         luamethod(ObjectRef, get_nametag_attributes),
1856         // LuaEntitySAO-only
1857         luamethod_aliased(ObjectRef, set_velocity, setvelocity),
1858         luamethod(ObjectRef, add_velocity),
1859         luamethod_aliased(ObjectRef, get_velocity, getvelocity),
1860         luamethod_aliased(ObjectRef, set_acceleration, setacceleration),
1861         luamethod_aliased(ObjectRef, get_acceleration, getacceleration),
1862         luamethod_aliased(ObjectRef, set_yaw, setyaw),
1863         luamethod_aliased(ObjectRef, get_yaw, getyaw),
1864         luamethod_aliased(ObjectRef, set_texture_mod, settexturemod),
1865         luamethod_aliased(ObjectRef, set_sprite, setsprite),
1866         luamethod(ObjectRef, get_entity_name),
1867         luamethod(ObjectRef, get_luaentity),
1868         // Player-only
1869         luamethod(ObjectRef, is_player),
1870         luamethod(ObjectRef, is_player_connected),
1871         luamethod(ObjectRef, get_player_name),
1872         luamethod(ObjectRef, get_player_velocity),
1873         luamethod(ObjectRef, get_look_dir),
1874         luamethod(ObjectRef, get_look_pitch),
1875         luamethod(ObjectRef, get_look_yaw),
1876         luamethod(ObjectRef, get_look_vertical),
1877         luamethod(ObjectRef, get_look_horizontal),
1878         luamethod(ObjectRef, set_look_horizontal),
1879         luamethod(ObjectRef, set_look_vertical),
1880         luamethod(ObjectRef, set_look_yaw),
1881         luamethod(ObjectRef, set_look_pitch),
1882         luamethod(ObjectRef, get_breath),
1883         luamethod(ObjectRef, set_breath),
1884         luamethod(ObjectRef, get_attribute),
1885         luamethod(ObjectRef, set_attribute),
1886         luamethod(ObjectRef, get_meta),
1887         luamethod(ObjectRef, set_inventory_formspec),
1888         luamethod(ObjectRef, get_inventory_formspec),
1889         luamethod(ObjectRef, set_formspec_prepend),
1890         luamethod(ObjectRef, get_formspec_prepend),
1891         luamethod(ObjectRef, get_player_control),
1892         luamethod(ObjectRef, get_player_control_bits),
1893         luamethod(ObjectRef, set_physics_override),
1894         luamethod(ObjectRef, get_physics_override),
1895         luamethod(ObjectRef, hud_add),
1896         luamethod(ObjectRef, hud_remove),
1897         luamethod(ObjectRef, hud_change),
1898         luamethod(ObjectRef, hud_get),
1899         luamethod(ObjectRef, hud_set_flags),
1900         luamethod(ObjectRef, hud_get_flags),
1901         luamethod(ObjectRef, hud_set_hotbar_itemcount),
1902         luamethod(ObjectRef, hud_get_hotbar_itemcount),
1903         luamethod(ObjectRef, hud_set_hotbar_image),
1904         luamethod(ObjectRef, hud_get_hotbar_image),
1905         luamethod(ObjectRef, hud_set_hotbar_selected_image),
1906         luamethod(ObjectRef, hud_get_hotbar_selected_image),
1907         luamethod(ObjectRef, set_sky),
1908         luamethod(ObjectRef, get_sky),
1909         luamethod(ObjectRef, set_clouds),
1910         luamethod(ObjectRef, get_clouds),
1911         luamethod(ObjectRef, override_day_night_ratio),
1912         luamethod(ObjectRef, get_day_night_ratio),
1913         luamethod(ObjectRef, set_local_animation),
1914         luamethod(ObjectRef, get_local_animation),
1915         luamethod(ObjectRef, set_eye_offset),
1916         luamethod(ObjectRef, get_eye_offset),
1917         {0,0}
1918 };