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