]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_object.cpp
Add ObjectRef:get_children() (#10480)
[dragonfireclient.git] / src / script / lua_api / l_object.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "lua_api/l_object.h"
21 #include <cmath>
22 #include "lua_api/l_internal.h"
23 #include "lua_api/l_inventory.h"
24 #include "lua_api/l_item.h"
25 #include "lua_api/l_playermeta.h"
26 #include "common/c_converter.h"
27 #include "common/c_content.h"
28 #include "log.h"
29 #include "tool.h"
30 #include "remoteplayer.h"
31 #include "server.h"
32 #include "hud.h"
33 #include "scripting_server.h"
34 #include "server/luaentity_sao.h"
35 #include "server/player_sao.h"
36 #include "server/serverinventorymgr.h"
37
38 /*
39         ObjectRef
40 */
41
42
43 ObjectRef* ObjectRef::checkobject(lua_State *L, int narg)
44 {
45         luaL_checktype(L, narg, LUA_TUSERDATA);
46         void *ud = luaL_checkudata(L, narg, className);
47         if (!ud) luaL_typerror(L, narg, className);
48         return *(ObjectRef**)ud;  // unbox pointer
49 }
50
51 ServerActiveObject* ObjectRef::getobject(ObjectRef *ref)
52 {
53         ServerActiveObject *co = ref->m_object;
54         if (co && co->isGone())
55                 return NULL;
56         return co;
57 }
58
59 LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
60 {
61         ServerActiveObject *obj = getobject(ref);
62         if (obj == NULL)
63                 return NULL;
64         if (obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
65                 return NULL;
66         return (LuaEntitySAO*)obj;
67 }
68
69 PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
70 {
71         ServerActiveObject *obj = getobject(ref);
72         if (obj == NULL)
73                 return NULL;
74         if (obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
75                 return NULL;
76         return (PlayerSAO*)obj;
77 }
78
79 RemotePlayer *ObjectRef::getplayer(ObjectRef *ref)
80 {
81         PlayerSAO *playersao = getplayersao(ref);
82         if (playersao == NULL)
83                 return NULL;
84         return playersao->getPlayer();
85 }
86
87 // Exported functions
88
89 // garbage collector
90 int ObjectRef::gc_object(lua_State *L) {
91         ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
92         //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
93         delete o;
94         return 0;
95 }
96
97 // remove(self)
98 int ObjectRef::l_remove(lua_State *L)
99 {
100         GET_ENV_PTR;
101
102         ObjectRef *ref = checkobject(L, 1);
103         ServerActiveObject *co = getobject(ref);
104         if (co == NULL)
105                 return 0;
106         if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
107                 return 0;
108
109         co->clearChildAttachments();
110         co->clearParentAttachment();
111
112         verbosestream << "ObjectRef::l_remove(): id=" << co->getId() << std::endl;
113         co->m_pending_removal = true;
114         return 0;
115 }
116
117 // get_pos(self)
118 // returns: {x=num, y=num, z=num}
119 int ObjectRef::l_get_pos(lua_State *L)
120 {
121         NO_MAP_LOCK_REQUIRED;
122         ObjectRef *ref = checkobject(L, 1);
123         ServerActiveObject *co = getobject(ref);
124         if (co == NULL) return 0;
125         push_v3f(L, co->getBasePosition() / BS);
126         return 1;
127 }
128
129 // set_pos(self, pos)
130 int ObjectRef::l_set_pos(lua_State *L)
131 {
132         NO_MAP_LOCK_REQUIRED;
133         ObjectRef *ref = checkobject(L, 1);
134         ServerActiveObject *co = getobject(ref);
135         if (co == NULL) return 0;
136         // pos
137         v3f pos = checkFloatPos(L, 2);
138         // Do it
139         co->setPos(pos);
140         return 0;
141 }
142
143 // move_to(self, pos, continuous=false)
144 int ObjectRef::l_move_to(lua_State *L)
145 {
146         NO_MAP_LOCK_REQUIRED;
147         ObjectRef *ref = checkobject(L, 1);
148         ServerActiveObject *co = getobject(ref);
149         if (co == NULL) return 0;
150         // pos
151         v3f pos = checkFloatPos(L, 2);
152         // continuous
153         bool continuous = readParam<bool>(L, 3);
154         // Do it
155         co->moveTo(pos, continuous);
156         return 0;
157 }
158
159 // punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
160 int ObjectRef::l_punch(lua_State *L)
161 {
162         NO_MAP_LOCK_REQUIRED;
163         ObjectRef *ref = checkobject(L, 1);
164         ObjectRef *puncher_ref = checkobject(L, 2);
165         ServerActiveObject *co = getobject(ref);
166         ServerActiveObject *puncher = getobject(puncher_ref);
167         if (!co || !puncher)
168                 return 0;
169         v3f dir;
170         if (lua_type(L, 5) != LUA_TTABLE)
171                 dir = co->getBasePosition() - puncher->getBasePosition();
172         else
173                 dir = read_v3f(L, 5);
174         float time_from_last_punch = 1000000;
175         if (lua_isnumber(L, 3))
176                 time_from_last_punch = lua_tonumber(L, 3);
177         ToolCapabilities toolcap = read_tool_capabilities(L, 4);
178         dir.normalize();
179
180         u16 src_original_hp = co->getHP();
181         u16 dst_origin_hp = puncher->getHP();
182
183         // Do it
184         u16 wear = co->punch(dir, &toolcap, puncher, time_from_last_punch);
185         lua_pushnumber(L, wear);
186
187         // If the punched is a player, and its HP changed
188         if (src_original_hp != co->getHP() &&
189                         co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
190                 getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co,
191                                 PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher));
192         }
193
194         // If the puncher is a player, and its HP changed
195         if (dst_origin_hp != puncher->getHP() &&
196                         puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
197                 getServer(L)->SendPlayerHPOrDie((PlayerSAO *)puncher,
198                                 PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, co));
199         }
200         return 1;
201 }
202
203 // right_click(self, clicker); clicker = an another ObjectRef
204 int ObjectRef::l_right_click(lua_State *L)
205 {
206         NO_MAP_LOCK_REQUIRED;
207         ObjectRef *ref = checkobject(L, 1);
208         ObjectRef *ref2 = checkobject(L, 2);
209         ServerActiveObject *co = getobject(ref);
210         ServerActiveObject *co2 = getobject(ref2);
211         if (co == NULL) return 0;
212         if (co2 == NULL) return 0;
213         // Do it
214         co->rightClick(co2);
215         return 0;
216 }
217
218 // set_hp(self, hp)
219 // hp = number of hitpoints (2 * number of hearts)
220 // returns: nil
221 int ObjectRef::l_set_hp(lua_State *L)
222 {
223         NO_MAP_LOCK_REQUIRED;
224
225         // Get Object
226         ObjectRef *ref = checkobject(L, 1);
227         luaL_checknumber(L, 2);
228         ServerActiveObject *co = getobject(ref);
229         if (co == NULL)
230                 return 0;
231
232         // Get HP
233         int hp = lua_tonumber(L, 2);
234
235         // Get Reason
236         PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP);
237         reason.from_mod = true;
238         if (lua_istable(L, 3)) {
239                 lua_pushvalue(L, 3);
240
241                 lua_getfield(L, -1, "type");
242                 if (lua_isstring(L, -1) &&
243                                 !reason.setTypeFromString(readParam<std::string>(L, -1))) {
244                         errorstream << "Bad type given!" << std::endl;
245                 }
246                 lua_pop(L, 1);
247
248                 reason.lua_reference = luaL_ref(L, LUA_REGISTRYINDEX);
249         }
250
251         // Do it
252         co->setHP(hp, reason);
253         if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
254                 getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, reason);
255
256         if (reason.hasLuaReference())
257                 luaL_unref(L, LUA_REGISTRYINDEX, reason.lua_reference);
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 (getServerInventoryMgr(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)
307                 return 0;
308
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)
320                 return 0;
321
322         lua_pushinteger(L, co->getWieldIndex() + 1);
323         return 1;
324 }
325
326 // get_wielded_item(self)
327 int ObjectRef::l_get_wielded_item(lua_State *L)
328 {
329         NO_MAP_LOCK_REQUIRED;
330         ObjectRef *ref = checkobject(L, 1);
331         ServerActiveObject *co = getobject(ref);
332         if (!co) {
333                 // Empty ItemStack
334                 LuaItemStack::create(L, ItemStack());
335                 return 1;
336         }
337
338         ItemStack selected_item;
339         co->getWieldedItem(&selected_item, nullptr);
340         LuaItemStack::create(L, selected_item);
341         return 1;
342 }
343
344 // set_wielded_item(self, itemstack or itemstring or table or nil)
345 int ObjectRef::l_set_wielded_item(lua_State *L)
346 {
347         NO_MAP_LOCK_REQUIRED;
348         ObjectRef *ref = checkobject(L, 1);
349         ServerActiveObject *co = getobject(ref);
350         if (co == NULL) return 0;
351         // Do it
352         ItemStack item = read_item(L, 2, getServer(L)->idef());
353         bool success = co->setWieldedItem(item);
354         if (success && co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
355                 getServer(L)->SendInventory((PlayerSAO *)co, true);
356         }
357         lua_pushboolean(L, success);
358         return 1;
359 }
360
361 // set_armor_groups(self, groups)
362 int ObjectRef::l_set_armor_groups(lua_State *L)
363 {
364         NO_MAP_LOCK_REQUIRED;
365         ObjectRef *ref = checkobject(L, 1);
366         ServerActiveObject *co = getobject(ref);
367         if (co == NULL) return 0;
368         // Do it
369         ItemGroupList groups;
370         read_groups(L, 2, groups);
371         co->setArmorGroups(groups);
372         return 0;
373 }
374
375 // get_armor_groups(self)
376 int ObjectRef::l_get_armor_groups(lua_State *L)
377 {
378         NO_MAP_LOCK_REQUIRED;
379         ObjectRef *ref = checkobject(L, 1);
380         ServerActiveObject *co = getobject(ref);
381         if (co == NULL)
382                 return 0;
383         // Do it
384         push_groups(L, co->getArmorGroups());
385         return 1;
386 }
387
388 // set_physics_override(self, physics_override_speed, physics_override_jump,
389 //                      physics_override_gravity, sneak, sneak_glitch, new_move)
390 int ObjectRef::l_set_physics_override(lua_State *L)
391 {
392         NO_MAP_LOCK_REQUIRED;
393         ObjectRef *ref = checkobject(L, 1);
394         PlayerSAO *co = (PlayerSAO *) getobject(ref);
395         if (co == NULL) return 0;
396         // Do it
397         if (lua_istable(L, 2)) {
398                 co->m_physics_override_speed = getfloatfield_default(
399                                 L, 2, "speed", co->m_physics_override_speed);
400                 co->m_physics_override_jump = getfloatfield_default(
401                                 L, 2, "jump", co->m_physics_override_jump);
402                 co->m_physics_override_gravity = getfloatfield_default(
403                                 L, 2, "gravity", co->m_physics_override_gravity);
404                 co->m_physics_override_sneak = getboolfield_default(
405                                 L, 2, "sneak", co->m_physics_override_sneak);
406                 co->m_physics_override_sneak_glitch = getboolfield_default(
407                                 L, 2, "sneak_glitch", co->m_physics_override_sneak_glitch);
408                 co->m_physics_override_new_move = getboolfield_default(
409                                 L, 2, "new_move", co->m_physics_override_new_move);
410                 co->m_physics_override_sent = false;
411         } else {
412                 // old, non-table format
413                 if (!lua_isnil(L, 2)) {
414                         co->m_physics_override_speed = lua_tonumber(L, 2);
415                         co->m_physics_override_sent = false;
416                 }
417                 if (!lua_isnil(L, 3)) {
418                         co->m_physics_override_jump = lua_tonumber(L, 3);
419                         co->m_physics_override_sent = false;
420                 }
421                 if (!lua_isnil(L, 4)) {
422                         co->m_physics_override_gravity = lua_tonumber(L, 4);
423                         co->m_physics_override_sent = false;
424                 }
425         }
426         return 0;
427 }
428
429 // get_physics_override(self)
430 int ObjectRef::l_get_physics_override(lua_State *L)
431 {
432         NO_MAP_LOCK_REQUIRED;
433         ObjectRef *ref = checkobject(L, 1);
434         PlayerSAO *co = (PlayerSAO *)getobject(ref);
435         if (co == NULL)
436                 return 0;
437         // Do it
438         lua_newtable(L);
439         lua_pushnumber(L, co->m_physics_override_speed);
440         lua_setfield(L, -2, "speed");
441         lua_pushnumber(L, co->m_physics_override_jump);
442         lua_setfield(L, -2, "jump");
443         lua_pushnumber(L, co->m_physics_override_gravity);
444         lua_setfield(L, -2, "gravity");
445         lua_pushboolean(L, co->m_physics_override_sneak);
446         lua_setfield(L, -2, "sneak");
447         lua_pushboolean(L, co->m_physics_override_sneak_glitch);
448         lua_setfield(L, -2, "sneak_glitch");
449         lua_pushboolean(L, co->m_physics_override_new_move);
450         lua_setfield(L, -2, "new_move");
451         return 1;
452 }
453
454 // set_animation(self, frame_range, frame_speed, frame_blend, frame_loop)
455 int ObjectRef::l_set_animation(lua_State *L)
456 {
457         NO_MAP_LOCK_REQUIRED;
458         ObjectRef *ref = checkobject(L, 1);
459         ServerActiveObject *co = getobject(ref);
460         if (co == NULL) return 0;
461         // Do it
462         v2f frames = v2f(1, 1);
463         if (!lua_isnil(L, 2))
464                 frames = readParam<v2f>(L, 2);
465         float frame_speed = 15;
466         if (!lua_isnil(L, 3))
467                 frame_speed = lua_tonumber(L, 3);
468         float frame_blend = 0;
469         if (!lua_isnil(L, 4))
470                 frame_blend = lua_tonumber(L, 4);
471         bool frame_loop = true;
472         if (lua_isboolean(L, 5))
473                 frame_loop = readParam<bool>(L, 5);
474         co->setAnimation(frames, frame_speed, frame_blend, frame_loop);
475         return 0;
476 }
477
478 // get_animation(self)
479 int ObjectRef::l_get_animation(lua_State *L)
480 {
481         NO_MAP_LOCK_REQUIRED;
482         ObjectRef *ref = checkobject(L, 1);
483         ServerActiveObject *co = getobject(ref);
484         if (co == NULL)
485                 return 0;
486         // Do it
487         v2f frames = v2f(1,1);
488         float frame_speed = 15;
489         float frame_blend = 0;
490         bool frame_loop = true;
491         co->getAnimation(&frames, &frame_speed, &frame_blend, &frame_loop);
492
493         push_v2f(L, frames);
494         lua_pushnumber(L, frame_speed);
495         lua_pushnumber(L, frame_blend);
496         lua_pushboolean(L, frame_loop);
497         return 4;
498 }
499
500 // set_local_animation(self, {stand/idle}, {walk}, {dig}, {walk+dig}, frame_speed)
501 int ObjectRef::l_set_local_animation(lua_State *L)
502 {
503         NO_MAP_LOCK_REQUIRED;
504         ObjectRef *ref = checkobject(L, 1);
505         RemotePlayer *player = getplayer(ref);
506         if (player == NULL)
507                 return 0;
508         // Do it
509         v2s32 frames[4];
510         for (int i=0;i<4;i++) {
511                 if (!lua_isnil(L, 2+1))
512                         frames[i] = read_v2s32(L, 2+i);
513         }
514         float frame_speed = 30;
515         if (!lua_isnil(L, 6))
516                 frame_speed = lua_tonumber(L, 6);
517
518         getServer(L)->setLocalPlayerAnimations(player, frames, frame_speed);
519         lua_pushboolean(L, true);
520         return 1;
521 }
522
523 // get_local_animation(self)
524 int ObjectRef::l_get_local_animation(lua_State *L)
525 {
526         NO_MAP_LOCK_REQUIRED;
527         ObjectRef *ref = checkobject(L, 1);
528         RemotePlayer *player = getplayer(ref);
529         if (player == NULL)
530                 return 0;
531
532         v2s32 frames[4];
533         float frame_speed;
534         player->getLocalAnimations(frames, &frame_speed);
535
536         for (const v2s32 &frame : frames) {
537                 push_v2s32(L, frame);
538         }
539
540         lua_pushnumber(L, frame_speed);
541         return 5;
542 }
543
544 // set_eye_offset(self, v3f first pv, v3f third pv)
545 int ObjectRef::l_set_eye_offset(lua_State *L)
546 {
547         NO_MAP_LOCK_REQUIRED;
548         ObjectRef *ref = checkobject(L, 1);
549         RemotePlayer *player = getplayer(ref);
550         if (player == NULL)
551                 return 0;
552         // Do it
553         v3f offset_first = v3f(0, 0, 0);
554         v3f offset_third = v3f(0, 0, 0);
555
556         if (!lua_isnil(L, 2))
557                 offset_first = read_v3f(L, 2);
558         if (!lua_isnil(L, 3))
559                 offset_third = read_v3f(L, 3);
560
561         // Prevent abuse of offset values (keep player always visible)
562         offset_third.X = rangelim(offset_third.X,-10,10);
563         offset_third.Z = rangelim(offset_third.Z,-5,5);
564         /* TODO: if possible: improve the camera colision detetion to allow Y <= -1.5) */
565         offset_third.Y = rangelim(offset_third.Y,-10,15); //1.5*BS
566
567         getServer(L)->setPlayerEyeOffset(player, offset_first, offset_third);
568         lua_pushboolean(L, true);
569         return 1;
570 }
571
572 // get_eye_offset(self)
573 int ObjectRef::l_get_eye_offset(lua_State *L)
574 {
575         NO_MAP_LOCK_REQUIRED;
576         ObjectRef *ref = checkobject(L, 1);
577         RemotePlayer *player = getplayer(ref);
578         if (player == NULL)
579                 return 0;
580         // Do it
581         push_v3f(L, player->eye_offset_first);
582         push_v3f(L, player->eye_offset_third);
583         return 2;
584 }
585
586 // send_mapblock(self, pos)
587 int ObjectRef::l_send_mapblock(lua_State *L)
588 {
589         NO_MAP_LOCK_REQUIRED;
590         ObjectRef *ref = checkobject(L, 1);
591
592         RemotePlayer *player = getplayer(ref);
593         if (!player)
594                 return 0;
595         v3s16 p = read_v3s16(L, 2);
596
597         session_t peer_id = player->getPeerId();
598         bool r = getServer(L)->SendBlock(peer_id, p);
599
600         lua_pushboolean(L, r);
601         return 1;
602 }
603
604 // set_animation_frame_speed(self, frame_speed)
605 int ObjectRef::l_set_animation_frame_speed(lua_State *L)
606 {
607         NO_MAP_LOCK_REQUIRED;
608         ObjectRef *ref = checkobject(L, 1);
609         ServerActiveObject *co = getobject(ref);
610         if (co == NULL)
611                 return 0;
612
613         // Do it
614         if (!lua_isnil(L, 2)) {
615                 float frame_speed = lua_tonumber(L, 2);
616                 co->setAnimationSpeed(frame_speed);
617                 lua_pushboolean(L, true);
618         } else {
619                 lua_pushboolean(L, false);
620         }
621         return 1;
622 }
623
624 // set_bone_position(self, std::string bone, v3f position, v3f rotation)
625 int ObjectRef::l_set_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) return 0;
631         // Do it
632         std::string bone;
633         if (!lua_isnil(L, 2))
634                 bone = readParam<std::string>(L, 2);
635         v3f position = v3f(0, 0, 0);
636         if (!lua_isnil(L, 3))
637                 position = check_v3f(L, 3);
638         v3f rotation = v3f(0, 0, 0);
639         if (!lua_isnil(L, 4))
640                 rotation = check_v3f(L, 4);
641         co->setBonePosition(bone, position, rotation);
642         return 0;
643 }
644
645 // get_bone_position(self, bone)
646 int ObjectRef::l_get_bone_position(lua_State *L)
647 {
648         NO_MAP_LOCK_REQUIRED;
649         ObjectRef *ref = checkobject(L, 1);
650         ServerActiveObject *co = getobject(ref);
651         if (co == NULL)
652                 return 0;
653         // Do it
654         std::string bone;
655         if (!lua_isnil(L, 2))
656                 bone = readParam<std::string>(L, 2);
657
658         v3f position = v3f(0, 0, 0);
659         v3f rotation = v3f(0, 0, 0);
660         co->getBonePosition(bone, &position, &rotation);
661
662         push_v3f(L, position);
663         push_v3f(L, rotation);
664         return 2;
665 }
666
667 // set_attach(self, parent, bone, position, rotation, force_visible)
668 int ObjectRef::l_set_attach(lua_State *L)
669 {
670         GET_ENV_PTR;
671
672         ObjectRef *ref = checkobject(L, 1);
673         ObjectRef *parent_ref = checkobject(L, 2);
674         ServerActiveObject *co = getobject(ref);
675         ServerActiveObject *parent = getobject(parent_ref);
676         if (co == NULL)
677                 return 0;
678
679         if (parent == NULL)
680                 return 0;
681
682         if (co == parent)
683                 throw LuaError("ObjectRef::set_attach: attaching object to itself is not allowed.");
684
685         // Do it
686         int parent_id = 0;
687         std::string bone;
688         v3f position = v3f(0, 0, 0);
689         v3f rotation = v3f(0, 0, 0);
690         bool force_visible;
691         co->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible);
692         if (parent_id) {
693                 ServerActiveObject *old_parent = env->getActiveObject(parent_id);
694                 old_parent->removeAttachmentChild(co->getId());
695         }
696
697         bone = "";
698         if (!lua_isnil(L, 3))
699                 bone = readParam<std::string>(L, 3);
700         position = v3f(0, 0, 0);
701         if (!lua_isnil(L, 4))
702                 position = read_v3f(L, 4);
703         rotation = v3f(0, 0, 0);
704         if (!lua_isnil(L, 5))
705                 rotation = read_v3f(L, 5);
706         force_visible = readParam<bool>(L, 6, false);
707         co->setAttachment(parent->getId(), bone, position, rotation, force_visible);
708         parent->addAttachmentChild(co->getId());
709         return 0;
710 }
711
712 // get_attach(self)
713 int ObjectRef::l_get_attach(lua_State *L)
714 {
715         GET_ENV_PTR;
716
717         ObjectRef *ref = checkobject(L, 1);
718         ServerActiveObject *co = getobject(ref);
719         if (co == NULL)
720                 return 0;
721
722         // Do it
723         int parent_id = 0;
724         std::string bone;
725         v3f position = v3f(0, 0, 0);
726         v3f rotation = v3f(0, 0, 0);
727         bool force_visible;
728         co->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible);
729         if (!parent_id)
730                 return 0;
731         ServerActiveObject *parent = env->getActiveObject(parent_id);
732
733         getScriptApiBase(L)->objectrefGetOrCreate(L, parent);
734         lua_pushlstring(L, bone.c_str(), bone.size());
735         push_v3f(L, position);
736         push_v3f(L, rotation);
737         lua_pushboolean(L, force_visible);
738         return 5;
739 }
740
741 // get_children(self)
742 int ObjectRef::l_get_children(lua_State *L)
743 {
744         GET_ENV_PTR;
745
746         ObjectRef *ref = checkobject(L, 1);
747         ServerActiveObject *sao = getobject(ref);
748         if (sao == nullptr)
749                 return 0;
750
751         const std::unordered_set<int> child_ids = sao->getAttachmentChildIds();
752         int i = 0;
753         lua_createtable(L, child_ids.size(), 0);
754         for (const int id : child_ids) {
755                 ServerActiveObject *child = env->getActiveObject(id);
756                 getScriptApiBase(L)->objectrefGetOrCreate(L, child);
757                 lua_rawseti(L, -2, ++i);
758         }
759         return 1;
760 }
761
762 // set_detach(self)
763 int ObjectRef::l_set_detach(lua_State *L)
764 {
765         GET_ENV_PTR;
766
767         ObjectRef *ref = checkobject(L, 1);
768         ServerActiveObject *co = getobject(ref);
769         if (co == NULL)
770                 return 0;
771
772         co->clearParentAttachment();
773         return 0;
774 }
775
776 // set_properties(self, properties)
777 int ObjectRef::l_set_properties(lua_State *L)
778 {
779         NO_MAP_LOCK_REQUIRED;
780         ObjectRef *ref = checkobject(L, 1);
781         ServerActiveObject *co = getobject(ref);
782         if (!co)
783                 return 0;
784
785         ObjectProperties *prop = co->accessObjectProperties();
786         if (!prop)
787                 return 0;
788
789         read_object_properties(L, 2, co, prop, getServer(L)->idef());
790         co->notifyObjectPropertiesModified();
791         return 0;
792 }
793
794 // get_properties(self)
795 int ObjectRef::l_get_properties(lua_State *L)
796 {
797         NO_MAP_LOCK_REQUIRED;
798         ObjectRef *ref = checkobject(L, 1);
799         ServerActiveObject *co = getobject(ref);
800         if (co == NULL)
801                 return 0;
802         ObjectProperties *prop = co->accessObjectProperties();
803         if (!prop)
804                 return 0;
805         push_object_properties(L, prop);
806         return 1;
807 }
808
809 // is_player(self)
810 int ObjectRef::l_is_player(lua_State *L)
811 {
812         NO_MAP_LOCK_REQUIRED;
813         ObjectRef *ref = checkobject(L, 1);
814         RemotePlayer *player = getplayer(ref);
815         lua_pushboolean(L, (player != NULL));
816         return 1;
817 }
818
819 // set_nametag_attributes(self, attributes)
820 int ObjectRef::l_set_nametag_attributes(lua_State *L)
821 {
822         NO_MAP_LOCK_REQUIRED;
823         ObjectRef *ref = checkobject(L, 1);
824         ServerActiveObject *co = getobject(ref);
825
826         if (co == NULL)
827                 return 0;
828         ObjectProperties *prop = co->accessObjectProperties();
829         if (!prop)
830                 return 0;
831
832         lua_getfield(L, 2, "color");
833         if (!lua_isnil(L, -1)) {
834                 video::SColor color = prop->nametag_color;
835                 read_color(L, -1, &color);
836                 prop->nametag_color = color;
837         }
838         lua_pop(L, 1);
839
840         std::string nametag = getstringfield_default(L, 2, "text", "");
841         prop->nametag = nametag;
842
843         co->notifyObjectPropertiesModified();
844         lua_pushboolean(L, true);
845         return 1;
846 }
847
848 // get_nametag_attributes(self)
849 int ObjectRef::l_get_nametag_attributes(lua_State *L)
850 {
851         NO_MAP_LOCK_REQUIRED;
852         ObjectRef *ref = checkobject(L, 1);
853         ServerActiveObject *co = getobject(ref);
854
855         if (co == NULL)
856                 return 0;
857         ObjectProperties *prop = co->accessObjectProperties();
858         if (!prop)
859                 return 0;
860
861         video::SColor color = prop->nametag_color;
862
863         lua_newtable(L);
864         push_ARGB8(L, color);
865         lua_setfield(L, -2, "color");
866         lua_pushstring(L, prop->nametag.c_str());
867         lua_setfield(L, -2, "text");
868         return 1;
869 }
870
871 /* LuaEntitySAO-only */
872
873 // set_velocity(self, {x=num, y=num, z=num})
874 int ObjectRef::l_set_velocity(lua_State *L)
875 {
876         NO_MAP_LOCK_REQUIRED;
877         ObjectRef *ref = checkobject(L, 1);
878         LuaEntitySAO *co = getluaobject(ref);
879         if (co == NULL) return 0;
880         v3f pos = checkFloatPos(L, 2);
881         // Do it
882         co->setVelocity(pos);
883         return 0;
884 }
885
886 // add_velocity(self, {x=num, y=num, z=num})
887 int ObjectRef::l_add_velocity(lua_State *L)
888 {
889         NO_MAP_LOCK_REQUIRED;
890         ObjectRef *ref = checkobject(L, 1);
891         v3f vel = checkFloatPos(L, 2);
892
893         ServerActiveObject *obj = getobject(ref);
894         if (obj == nullptr)
895                 return 0;
896
897         if (obj->getType() == ACTIVEOBJECT_TYPE_LUAENTITY) {
898                 LuaEntitySAO *co = dynamic_cast<LuaEntitySAO*>(obj);
899                 co->addVelocity(vel);
900         } else if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
901                 PlayerSAO *player = dynamic_cast<PlayerSAO*>(obj);
902                 player->setMaxSpeedOverride(vel);
903                 getServer(L)->SendPlayerSpeed(player->getPeerID(), vel);
904         }
905
906         return 0;
907 }
908
909 // get_velocity(self)
910 int ObjectRef::l_get_velocity(lua_State *L)
911 {
912         NO_MAP_LOCK_REQUIRED;
913         ObjectRef *ref = checkobject(L, 1);
914
915         ServerActiveObject *obj = getobject(ref);
916         if (obj == nullptr)
917                 return 0;
918
919         if (obj->getType() == ACTIVEOBJECT_TYPE_LUAENTITY) {
920                 LuaEntitySAO *co = dynamic_cast<LuaEntitySAO*>(obj);
921                 v3f v = co->getVelocity();
922                 pushFloatPos(L, v);
923                 return 1;
924         } else if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
925                 RemotePlayer *player = dynamic_cast<PlayerSAO*>(obj)->getPlayer();
926                 push_v3f(L, player->getSpeed() / BS);
927                 return 1;
928         }
929
930         lua_pushnil(L);
931         return 1;
932 }
933
934 // set_acceleration(self, {x=num, y=num, z=num})
935 int ObjectRef::l_set_acceleration(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         // pos
942         v3f pos = checkFloatPos(L, 2);
943         // Do it
944         co->setAcceleration(pos);
945         return 0;
946 }
947
948 // get_acceleration(self)
949 int ObjectRef::l_get_acceleration(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         v3f v = co->getAcceleration();
957         pushFloatPos(L, v);
958         return 1;
959 }
960
961 // set_rotation(self, {x=num, y=num, z=num})
962 // Each 'num' is in radians
963 int ObjectRef::l_set_rotation(lua_State *L)
964 {
965         NO_MAP_LOCK_REQUIRED;
966         ObjectRef *ref = checkobject(L, 1);
967         LuaEntitySAO *co = getluaobject(ref);
968         if (!co)
969                 return 0;
970
971         v3f rotation = check_v3f(L, 2) * core::RADTODEG;
972         co->setRotation(rotation);
973         return 0;
974 }
975
976 // get_rotation(self)
977 // returns: {x=num, y=num, z=num}
978 // Each 'num' is in radians
979 int ObjectRef::l_get_rotation(lua_State *L)
980 {
981         NO_MAP_LOCK_REQUIRED;
982         ObjectRef *ref = checkobject(L, 1);
983         LuaEntitySAO *co = getluaobject(ref);
984         if (!co)
985                 return 0;
986
987         lua_newtable(L);
988         v3f rotation = co->getRotation() * core::DEGTORAD;
989         push_v3f(L, rotation);
990         return 1;
991 }
992
993 // set_yaw(self, radians)
994 int ObjectRef::l_set_yaw(lua_State *L)
995 {
996         NO_MAP_LOCK_REQUIRED;
997         ObjectRef *ref = checkobject(L, 1);
998         LuaEntitySAO *co = getluaobject(ref);
999
1000         if (co == NULL) return 0;
1001         if (isNaN(L, 2))
1002                 throw LuaError("ObjectRef::set_yaw: NaN value is not allowed.");
1003
1004         float yaw = readParam<float>(L, 2) * core::RADTODEG;
1005         co->setRotation(v3f(0, yaw, 0));
1006         return 0;
1007 }
1008
1009 // get_yaw(self)
1010 int ObjectRef::l_get_yaw(lua_State *L)
1011 {
1012         NO_MAP_LOCK_REQUIRED;
1013         ObjectRef *ref = checkobject(L, 1);
1014         LuaEntitySAO *co = getluaobject(ref);
1015         if (!co)
1016                 return 0;
1017
1018         float yaw = co->getRotation().Y * core::DEGTORAD;
1019         lua_pushnumber(L, yaw);
1020         return 1;
1021 }
1022
1023 // set_texture_mod(self, mod)
1024 int ObjectRef::l_set_texture_mod(lua_State *L)
1025 {
1026         NO_MAP_LOCK_REQUIRED;
1027         ObjectRef *ref = checkobject(L, 1);
1028         LuaEntitySAO *co = getluaobject(ref);
1029         if (co == NULL) return 0;
1030         // Do it
1031         std::string mod = luaL_checkstring(L, 2);
1032         co->setTextureMod(mod);
1033         return 0;
1034 }
1035
1036 // get_texture_mod(self)
1037 int ObjectRef::l_get_texture_mod(lua_State *L)
1038 {
1039         NO_MAP_LOCK_REQUIRED;
1040         ObjectRef *ref = checkobject(L, 1);
1041         LuaEntitySAO *co = getluaobject(ref);
1042         if (co == NULL) return 0;
1043         // Do it
1044         std::string mod = co->getTextureMod();
1045         lua_pushstring(L, mod.c_str());
1046         return 1;
1047 }
1048
1049 // set_sprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
1050 //           select_horiz_by_yawpitch=false)
1051 int ObjectRef::l_set_sprite(lua_State *L)
1052 {
1053         NO_MAP_LOCK_REQUIRED;
1054         ObjectRef *ref = checkobject(L, 1);
1055         LuaEntitySAO *co = getluaobject(ref);
1056         if (co == NULL) return 0;
1057         // Do it
1058         v2s16 p(0,0);
1059         if (!lua_isnil(L, 2))
1060                 p = readParam<v2s16>(L, 2);
1061         int num_frames = 1;
1062         if (!lua_isnil(L, 3))
1063                 num_frames = lua_tonumber(L, 3);
1064         float framelength = 0.2;
1065         if (!lua_isnil(L, 4))
1066                 framelength = lua_tonumber(L, 4);
1067         bool select_horiz_by_yawpitch = false;
1068         if (!lua_isnil(L, 5))
1069                 select_horiz_by_yawpitch = readParam<bool>(L, 5);
1070         co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
1071         return 0;
1072 }
1073
1074 // DEPRECATED
1075 // get_entity_name(self)
1076 int ObjectRef::l_get_entity_name(lua_State *L)
1077 {
1078         NO_MAP_LOCK_REQUIRED;
1079         ObjectRef *ref = checkobject(L, 1);
1080         LuaEntitySAO *co = getluaobject(ref);
1081         log_deprecated(L,"Deprecated call to \"get_entity_name");
1082         if (co == NULL) return 0;
1083         // Do it
1084         std::string name = co->getName();
1085         lua_pushstring(L, name.c_str());
1086         return 1;
1087 }
1088
1089 // get_luaentity(self)
1090 int ObjectRef::l_get_luaentity(lua_State *L)
1091 {
1092         NO_MAP_LOCK_REQUIRED;
1093         ObjectRef *ref = checkobject(L, 1);
1094         LuaEntitySAO *co = getluaobject(ref);
1095         if (co == NULL) return 0;
1096         // Do it
1097         luaentity_get(L, co->getId());
1098         return 1;
1099 }
1100
1101 /* Player-only */
1102
1103 // is_player_connected(self)
1104 int ObjectRef::l_is_player_connected(lua_State *L)
1105 {
1106         NO_MAP_LOCK_REQUIRED;
1107         // This method was once added for a bugfix, but never documented
1108         log_deprecated(L, "is_player_connected is undocumented and "
1109                 "will be removed in a future release");
1110         ObjectRef *ref = checkobject(L, 1);
1111         RemotePlayer *player = getplayer(ref);
1112         lua_pushboolean(L, (player != NULL && player->getPeerId() != PEER_ID_INEXISTENT));
1113         return 1;
1114 }
1115
1116 // get_player_name(self)
1117 int ObjectRef::l_get_player_name(lua_State *L)
1118 {
1119         NO_MAP_LOCK_REQUIRED;
1120         ObjectRef *ref = checkobject(L, 1);
1121         RemotePlayer *player = getplayer(ref);
1122         if (player == NULL) {
1123                 lua_pushlstring(L, "", 0);
1124                 return 1;
1125         }
1126         // Do it
1127         lua_pushstring(L, player->getName());
1128         return 1;
1129 }
1130
1131 // get_look_dir(self)
1132 int ObjectRef::l_get_look_dir(lua_State *L)
1133 {
1134         NO_MAP_LOCK_REQUIRED;
1135         ObjectRef *ref = checkobject(L, 1);
1136         PlayerSAO* co = getplayersao(ref);
1137         if (co == NULL) return 0;
1138         // Do it
1139         float pitch = co->getRadLookPitchDep();
1140         float yaw = co->getRadYawDep();
1141         v3f v(std::cos(pitch) * std::cos(yaw), std::sin(pitch), std::cos(pitch) *
1142                 std::sin(yaw));
1143         push_v3f(L, v);
1144         return 1;
1145 }
1146
1147 // DEPRECATED
1148 // get_look_pitch(self)
1149 int ObjectRef::l_get_look_pitch(lua_State *L)
1150 {
1151         NO_MAP_LOCK_REQUIRED;
1152
1153         log_deprecated(L,
1154                 "Deprecated call to get_look_pitch, use get_look_vertical instead");
1155
1156         ObjectRef *ref = checkobject(L, 1);
1157         PlayerSAO* co = getplayersao(ref);
1158         if (co == NULL) return 0;
1159         // Do it
1160         lua_pushnumber(L, co->getRadLookPitchDep());
1161         return 1;
1162 }
1163
1164 // DEPRECATED
1165 // get_look_yaw(self)
1166 int ObjectRef::l_get_look_yaw(lua_State *L)
1167 {
1168         NO_MAP_LOCK_REQUIRED;
1169
1170         log_deprecated(L,
1171                 "Deprecated call to get_look_yaw, use get_look_horizontal instead");
1172
1173         ObjectRef *ref = checkobject(L, 1);
1174         PlayerSAO* co = getplayersao(ref);
1175         if (co == NULL) return 0;
1176         // Do it
1177         lua_pushnumber(L, co->getRadYawDep());
1178         return 1;
1179 }
1180
1181 // get_look_pitch2(self)
1182 int ObjectRef::l_get_look_vertical(lua_State *L)
1183 {
1184         NO_MAP_LOCK_REQUIRED;
1185         ObjectRef *ref = checkobject(L, 1);
1186         PlayerSAO* co = getplayersao(ref);
1187         if (co == NULL) return 0;
1188         // Do it
1189         lua_pushnumber(L, co->getRadLookPitch());
1190         return 1;
1191 }
1192
1193 // get_look_yaw2(self)
1194 int ObjectRef::l_get_look_horizontal(lua_State *L)
1195 {
1196         NO_MAP_LOCK_REQUIRED;
1197         ObjectRef *ref = checkobject(L, 1);
1198         PlayerSAO* co = getplayersao(ref);
1199         if (co == NULL) return 0;
1200         // Do it
1201         lua_pushnumber(L, co->getRadRotation().Y);
1202         return 1;
1203 }
1204
1205 // set_look_vertical(self, radians)
1206 int ObjectRef::l_set_look_vertical(lua_State *L)
1207 {
1208         NO_MAP_LOCK_REQUIRED;
1209         ObjectRef *ref = checkobject(L, 1);
1210         PlayerSAO* co = getplayersao(ref);
1211         if (co == NULL) return 0;
1212         float pitch = readParam<float>(L, 2) * core::RADTODEG;
1213         // Do it
1214         co->setLookPitchAndSend(pitch);
1215         return 1;
1216 }
1217
1218 // set_look_horizontal(self, radians)
1219 int ObjectRef::l_set_look_horizontal(lua_State *L)
1220 {
1221         NO_MAP_LOCK_REQUIRED;
1222         ObjectRef *ref = checkobject(L, 1);
1223         PlayerSAO* co = getplayersao(ref);
1224         if (co == NULL) return 0;
1225         float yaw = readParam<float>(L, 2) * core::RADTODEG;
1226         // Do it
1227         co->setPlayerYawAndSend(yaw);
1228         return 1;
1229 }
1230
1231 // DEPRECATED
1232 // set_look_pitch(self, radians)
1233 int ObjectRef::l_set_look_pitch(lua_State *L)
1234 {
1235         NO_MAP_LOCK_REQUIRED;
1236
1237         log_deprecated(L,
1238                 "Deprecated call to set_look_pitch, use set_look_vertical instead.");
1239
1240         ObjectRef *ref = checkobject(L, 1);
1241         PlayerSAO* co = getplayersao(ref);
1242         if (co == NULL) return 0;
1243         float pitch = readParam<float>(L, 2) * core::RADTODEG;
1244         // Do it
1245         co->setLookPitchAndSend(pitch);
1246         return 1;
1247 }
1248
1249 // DEPRECATED
1250 // set_look_yaw(self, radians)
1251 int ObjectRef::l_set_look_yaw(lua_State *L)
1252 {
1253         NO_MAP_LOCK_REQUIRED;
1254
1255         log_deprecated(L,
1256                 "Deprecated call to set_look_yaw, use set_look_horizontal instead.");
1257
1258         ObjectRef *ref = checkobject(L, 1);
1259         PlayerSAO* co = getplayersao(ref);
1260         if (co == NULL) return 0;
1261         float yaw = readParam<float>(L, 2) * core::RADTODEG;
1262         // Do it
1263         co->setPlayerYawAndSend(yaw);
1264         return 1;
1265 }
1266
1267 // set_fov(self, degrees[, is_multiplier, transition_time])
1268 int ObjectRef::l_set_fov(lua_State *L)
1269 {
1270         NO_MAP_LOCK_REQUIRED;
1271         ObjectRef *ref = checkobject(L, 1);
1272         RemotePlayer *player = getplayer(ref);
1273         if (!player)
1274                 return 0;
1275
1276         player->setFov({
1277                 static_cast<f32>(luaL_checknumber(L, 2)),
1278                 readParam<bool>(L, 3, false),
1279                 lua_isnumber(L, 4) ? static_cast<f32>(luaL_checknumber(L, 4)) : 0.0f
1280         });
1281         getServer(L)->SendPlayerFov(player->getPeerId());
1282
1283         return 0;
1284 }
1285
1286 // get_fov(self)
1287 int ObjectRef::l_get_fov(lua_State *L)
1288 {
1289         NO_MAP_LOCK_REQUIRED;
1290         ObjectRef *ref = checkobject(L, 1);
1291         RemotePlayer *player = getplayer(ref);
1292         if (!player)
1293                 return 0;
1294
1295         PlayerFovSpec fov_spec = player->getFov();
1296         lua_pushnumber(L, fov_spec.fov);
1297         lua_pushboolean(L, fov_spec.is_multiplier);
1298         lua_pushnumber(L, fov_spec.transition_time);
1299
1300         return 3;
1301 }
1302
1303 // set_breath(self, breath)
1304 int ObjectRef::l_set_breath(lua_State *L)
1305 {
1306         NO_MAP_LOCK_REQUIRED;
1307         ObjectRef *ref = checkobject(L, 1);
1308         PlayerSAO* co = getplayersao(ref);
1309         if (co == NULL) return 0;
1310         u16 breath = luaL_checknumber(L, 2);
1311         co->setBreath(breath);
1312
1313         return 0;
1314 }
1315
1316 // get_breath(self)
1317 int ObjectRef::l_get_breath(lua_State *L)
1318 {
1319         NO_MAP_LOCK_REQUIRED;
1320         ObjectRef *ref = checkobject(L, 1);
1321         PlayerSAO* co = getplayersao(ref);
1322         if (co == NULL) return 0;
1323         // Do it
1324         u16 breath = co->getBreath();
1325         lua_pushinteger (L, breath);
1326         return 1;
1327 }
1328
1329 // set_attribute(self, attribute, value)
1330 int ObjectRef::l_set_attribute(lua_State *L)
1331 {
1332         log_deprecated(L,
1333                 "Deprecated call to set_attribute, use MetaDataRef methods instead.");
1334
1335         ObjectRef *ref = checkobject(L, 1);
1336         PlayerSAO* co = getplayersao(ref);
1337         if (co == NULL)
1338                 return 0;
1339
1340         std::string attr = luaL_checkstring(L, 2);
1341         if (lua_isnil(L, 3)) {
1342                 co->getMeta().removeString(attr);
1343         } else {
1344                 std::string value = luaL_checkstring(L, 3);
1345                 co->getMeta().setString(attr, value);
1346         }
1347         return 1;
1348 }
1349
1350 // get_attribute(self, attribute)
1351 int ObjectRef::l_get_attribute(lua_State *L)
1352 {
1353         log_deprecated(L,
1354                 "Deprecated call to get_attribute, use MetaDataRef methods instead.");
1355
1356         ObjectRef *ref = checkobject(L, 1);
1357         PlayerSAO* co = getplayersao(ref);
1358         if (co == NULL)
1359                 return 0;
1360
1361         std::string attr = luaL_checkstring(L, 2);
1362
1363         std::string value;
1364         if (co->getMeta().getStringToRef(attr, value)) {
1365                 lua_pushstring(L, value.c_str());
1366                 return 1;
1367         }
1368
1369         return 0;
1370 }
1371
1372
1373 // get_meta(self, attribute)
1374 int ObjectRef::l_get_meta(lua_State *L)
1375 {
1376         ObjectRef *ref = checkobject(L, 1);
1377         PlayerSAO *co = getplayersao(ref);
1378         if (co == NULL)
1379                 return 0;
1380
1381         PlayerMetaRef::create(L, &co->getMeta());
1382         return 1;
1383 }
1384
1385
1386 // set_inventory_formspec(self, formspec)
1387 int ObjectRef::l_set_inventory_formspec(lua_State *L)
1388 {
1389         NO_MAP_LOCK_REQUIRED;
1390         ObjectRef *ref = checkobject(L, 1);
1391         RemotePlayer *player = getplayer(ref);
1392         if (player == NULL) return 0;
1393         std::string formspec = luaL_checkstring(L, 2);
1394
1395         player->inventory_formspec = formspec;
1396         getServer(L)->reportInventoryFormspecModified(player->getName());
1397         lua_pushboolean(L, true);
1398         return 1;
1399 }
1400
1401 // get_inventory_formspec(self) -> formspec
1402 int ObjectRef::l_get_inventory_formspec(lua_State *L)
1403 {
1404         NO_MAP_LOCK_REQUIRED;
1405         ObjectRef *ref = checkobject(L, 1);
1406         RemotePlayer *player = getplayer(ref);
1407         if (player == NULL) return 0;
1408
1409         std::string formspec = player->inventory_formspec;
1410         lua_pushlstring(L, formspec.c_str(), formspec.size());
1411         return 1;
1412 }
1413
1414 // set_formspec_prepend(self, formspec)
1415 int ObjectRef::l_set_formspec_prepend(lua_State *L)
1416 {
1417         NO_MAP_LOCK_REQUIRED;
1418         ObjectRef *ref = checkobject(L, 1);
1419         RemotePlayer *player = getplayer(ref);
1420         if (player == NULL)
1421                 return 0;
1422
1423         std::string formspec = luaL_checkstring(L, 2);
1424
1425         player->formspec_prepend = formspec;
1426         getServer(L)->reportFormspecPrependModified(player->getName());
1427         lua_pushboolean(L, true);
1428         return 1;
1429 }
1430
1431 // get_formspec_prepend(self) -> formspec
1432 int ObjectRef::l_get_formspec_prepend(lua_State *L)
1433 {
1434         NO_MAP_LOCK_REQUIRED;
1435         ObjectRef *ref = checkobject(L, 1);
1436         RemotePlayer *player = getplayer(ref);
1437         if (player == NULL)
1438                  return 0;
1439
1440         std::string formspec = player->formspec_prepend;
1441         lua_pushlstring(L, formspec.c_str(), formspec.size());
1442         return 1;
1443 }
1444
1445 // get_player_control(self)
1446 int ObjectRef::l_get_player_control(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                 lua_pushlstring(L, "", 0);
1453                 return 1;
1454         }
1455
1456         const PlayerControl &control = player->getPlayerControl();
1457         lua_newtable(L);
1458         lua_pushboolean(L, control.up);
1459         lua_setfield(L, -2, "up");
1460         lua_pushboolean(L, control.down);
1461         lua_setfield(L, -2, "down");
1462         lua_pushboolean(L, control.left);
1463         lua_setfield(L, -2, "left");
1464         lua_pushboolean(L, control.right);
1465         lua_setfield(L, -2, "right");
1466         lua_pushboolean(L, control.jump);
1467         lua_setfield(L, -2, "jump");
1468         lua_pushboolean(L, control.aux1);
1469         lua_setfield(L, -2, "aux1");
1470         lua_pushboolean(L, control.sneak);
1471         lua_setfield(L, -2, "sneak");
1472         lua_pushboolean(L, control.dig);
1473         lua_setfield(L, -2, "dig");
1474         lua_pushboolean(L, control.place);
1475         lua_setfield(L, -2, "place");
1476         // Legacy fields to ensure mod compatibility
1477         lua_pushboolean(L, control.dig);
1478         lua_setfield(L, -2, "LMB");
1479         lua_pushboolean(L, control.place);
1480         lua_setfield(L, -2, "RMB");
1481         lua_pushboolean(L, control.zoom);
1482         lua_setfield(L, -2, "zoom");
1483         return 1;
1484 }
1485
1486 // get_player_control_bits(self)
1487 int ObjectRef::l_get_player_control_bits(lua_State *L)
1488 {
1489         NO_MAP_LOCK_REQUIRED;
1490         ObjectRef *ref = checkobject(L, 1);
1491         RemotePlayer *player = getplayer(ref);
1492         if (player == NULL) {
1493                 lua_pushlstring(L, "", 0);
1494                 return 1;
1495         }
1496         // Do it
1497         lua_pushnumber(L, player->keyPressed);
1498         return 1;
1499 }
1500
1501 // hud_add(self, form)
1502 int ObjectRef::l_hud_add(lua_State *L)
1503 {
1504         NO_MAP_LOCK_REQUIRED;
1505         ObjectRef *ref = checkobject(L, 1);
1506         RemotePlayer *player = getplayer(ref);
1507         if (player == NULL)
1508                 return 0;
1509
1510         HudElement *elem = new HudElement;
1511         read_hud_element(L, elem);
1512
1513         u32 id = getServer(L)->hudAdd(player, elem);
1514         if (id == U32_MAX) {
1515                 delete elem;
1516                 return 0;
1517         }
1518
1519         lua_pushnumber(L, id);
1520         return 1;
1521 }
1522
1523 // hud_remove(self, id)
1524 int ObjectRef::l_hud_remove(lua_State *L)
1525 {
1526         NO_MAP_LOCK_REQUIRED;
1527         ObjectRef *ref = checkobject(L, 1);
1528         RemotePlayer *player = getplayer(ref);
1529         if (player == NULL)
1530                 return 0;
1531
1532         u32 id = -1;
1533         if (!lua_isnil(L, 2))
1534                 id = lua_tonumber(L, 2);
1535
1536         if (!getServer(L)->hudRemove(player, id))
1537                 return 0;
1538
1539         lua_pushboolean(L, true);
1540         return 1;
1541 }
1542
1543 // hud_change(self, id, stat, data)
1544 int ObjectRef::l_hud_change(lua_State *L)
1545 {
1546         NO_MAP_LOCK_REQUIRED;
1547         ObjectRef *ref = checkobject(L, 1);
1548         RemotePlayer *player = getplayer(ref);
1549         if (player == NULL)
1550                 return 0;
1551
1552         u32 id = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : -1;
1553
1554         HudElement *e = player->getHud(id);
1555         if (!e)
1556                 return 0;
1557
1558         void *value = NULL;
1559         HudElementStat stat = read_hud_change(L, e, &value);
1560
1561         getServer(L)->hudChange(player, id, stat, value);
1562
1563         lua_pushboolean(L, true);
1564         return 1;
1565 }
1566
1567 // hud_get(self, id)
1568 int ObjectRef::l_hud_get(lua_State *L)
1569 {
1570         NO_MAP_LOCK_REQUIRED;
1571         ObjectRef *ref = checkobject(L, 1);
1572         RemotePlayer *player = getplayer(ref);
1573         if (player == NULL)
1574                 return 0;
1575
1576         u32 id = lua_tonumber(L, -1);
1577
1578         HudElement *e = player->getHud(id);
1579         if (!e)
1580                 return 0;
1581         push_hud_element(L, e);
1582         return 1;
1583 }
1584
1585 // hud_set_flags(self, flags)
1586 int ObjectRef::l_hud_set_flags(lua_State *L)
1587 {
1588         NO_MAP_LOCK_REQUIRED;
1589         ObjectRef *ref = checkobject(L, 1);
1590         RemotePlayer *player = getplayer(ref);
1591         if (player == NULL)
1592                 return 0;
1593
1594         u32 flags = 0;
1595         u32 mask  = 0;
1596         bool flag;
1597
1598         const EnumString *esp = es_HudBuiltinElement;
1599         for (int i = 0; esp[i].str; i++) {
1600                 if (getboolfield(L, 2, esp[i].str, flag)) {
1601                         flags |= esp[i].num * flag;
1602                         mask  |= esp[i].num;
1603                 }
1604         }
1605         if (!getServer(L)->hudSetFlags(player, flags, mask))
1606                 return 0;
1607
1608         lua_pushboolean(L, true);
1609         return 1;
1610 }
1611
1612 int ObjectRef::l_hud_get_flags(lua_State *L)
1613 {
1614         NO_MAP_LOCK_REQUIRED;
1615         ObjectRef *ref = checkobject(L, 1);
1616         RemotePlayer *player = getplayer(ref);
1617         if (player == NULL)
1618                 return 0;
1619
1620         lua_newtable(L);
1621         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE);
1622         lua_setfield(L, -2, "hotbar");
1623         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE);
1624         lua_setfield(L, -2, "healthbar");
1625         lua_pushboolean(L, player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE);
1626         lua_setfield(L, -2, "crosshair");
1627         lua_pushboolean(L, player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE);
1628         lua_setfield(L, -2, "wielditem");
1629         lua_pushboolean(L, player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE);
1630         lua_setfield(L, -2, "breathbar");
1631         lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
1632         lua_setfield(L, -2, "minimap");
1633         lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE);
1634         lua_setfield(L, -2, "minimap_radar");
1635
1636         return 1;
1637 }
1638
1639 // hud_set_hotbar_itemcount(self, hotbar_itemcount)
1640 int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
1641 {
1642         NO_MAP_LOCK_REQUIRED;
1643         ObjectRef *ref = checkobject(L, 1);
1644         RemotePlayer *player = getplayer(ref);
1645         if (player == NULL)
1646                 return 0;
1647
1648         s32 hotbar_itemcount = lua_tonumber(L, 2);
1649
1650         if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
1651                 return 0;
1652
1653         lua_pushboolean(L, true);
1654         return 1;
1655 }
1656
1657 // hud_get_hotbar_itemcount(self)
1658 int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
1659 {
1660         NO_MAP_LOCK_REQUIRED;
1661         ObjectRef *ref = checkobject(L, 1);
1662         RemotePlayer *player = getplayer(ref);
1663         if (player == NULL)
1664                 return 0;
1665
1666         lua_pushnumber(L, player->getHotbarItemcount());
1667         return 1;
1668 }
1669
1670 // hud_set_hotbar_image(self, name)
1671 int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
1672 {
1673         NO_MAP_LOCK_REQUIRED;
1674         ObjectRef *ref = checkobject(L, 1);
1675         RemotePlayer *player = getplayer(ref);
1676         if (player == NULL)
1677                 return 0;
1678
1679         std::string name = readParam<std::string>(L, 2);
1680
1681         getServer(L)->hudSetHotbarImage(player, name);
1682         return 1;
1683 }
1684
1685 // hud_get_hotbar_image(self)
1686 int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
1687 {
1688         NO_MAP_LOCK_REQUIRED;
1689         ObjectRef *ref = checkobject(L, 1);
1690         RemotePlayer *player = getplayer(ref);
1691         if (player == NULL)
1692                 return 0;
1693
1694         const std::string &name = player->getHotbarImage();
1695         lua_pushlstring(L, name.c_str(), name.size());
1696         return 1;
1697 }
1698
1699 // hud_set_hotbar_selected_image(self, name)
1700 int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
1701 {
1702         NO_MAP_LOCK_REQUIRED;
1703         ObjectRef *ref = checkobject(L, 1);
1704         RemotePlayer *player = getplayer(ref);
1705         if (player == NULL)
1706                 return 0;
1707
1708         std::string name = readParam<std::string>(L, 2);
1709
1710         getServer(L)->hudSetHotbarSelectedImage(player, name);
1711         return 1;
1712 }
1713
1714 // hud_get_hotbar_selected_image(self)
1715 int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
1716 {
1717         NO_MAP_LOCK_REQUIRED;
1718         ObjectRef *ref = checkobject(L, 1);
1719         RemotePlayer *player = getplayer(ref);
1720         if (player == NULL)
1721                 return 0;
1722
1723         const std::string &name = player->getHotbarSelectedImage();
1724         lua_pushlstring(L, name.c_str(), name.size());
1725         return 1;
1726 }
1727
1728 // set_sky(self, {base_color=, type=, textures=, clouds=, sky_colors={}})
1729 int ObjectRef::l_set_sky(lua_State *L)
1730 {
1731         NO_MAP_LOCK_REQUIRED;
1732         ObjectRef *ref = checkobject(L, 1);
1733         RemotePlayer *player = getplayer(ref);
1734         if (!player)
1735                 return 0;
1736
1737         bool is_colorspec = is_color_table(L, 2);
1738
1739         SkyboxParams skybox_params = player->getSkyParams();
1740         if (lua_istable(L, 2) && !is_colorspec) {
1741                 lua_getfield(L, 2, "base_color");
1742                 if (!lua_isnil(L, -1))
1743                         read_color(L, -1, &skybox_params.bgcolor);
1744                 lua_pop(L, 1);
1745
1746                 lua_getfield(L, 2, "type");
1747                 if (!lua_isnil(L, -1))
1748                         skybox_params.type = luaL_checkstring(L, -1);
1749                 lua_pop(L, 1);
1750
1751                 lua_getfield(L, 2, "textures");
1752                 skybox_params.textures.clear();
1753                 if (lua_istable(L, -1) && skybox_params.type == "skybox") {
1754                         lua_pushnil(L);
1755                         while (lua_next(L, -2) != 0) {
1756                                 // Key is at index -2 and value at index -1
1757                                 skybox_params.textures.emplace_back(readParam<std::string>(L, -1));
1758                                 // Removes the value, but keeps the key for iteration
1759                                 lua_pop(L, 1);
1760                         }
1761                 }
1762                 lua_pop(L, 1);
1763
1764                 /*
1765                 We want to avoid crashes, so we're checking even if we're not using them.
1766                 However, we want to ensure that the skybox can be set to nil when
1767                 using "regular" or "plain" skybox modes as textures aren't needed.
1768                 */
1769
1770                 if (skybox_params.textures.size() != 6 && skybox_params.textures.size() > 0)
1771                         throw LuaError("Skybox expects 6 textures!");
1772
1773                 skybox_params.clouds = getboolfield_default(L, 2,
1774                         "clouds", skybox_params.clouds);
1775
1776                 lua_getfield(L, 2, "sky_color");
1777                 if (lua_istable(L, -1)) {
1778                         lua_getfield(L, -1, "day_sky");
1779                         read_color(L, -1, &skybox_params.sky_color.day_sky);
1780                         lua_pop(L, 1);
1781
1782                         lua_getfield(L, -1, "day_horizon");
1783                         read_color(L, -1, &skybox_params.sky_color.day_horizon);
1784                         lua_pop(L, 1);
1785
1786                         lua_getfield(L, -1, "dawn_sky");
1787                         read_color(L, -1, &skybox_params.sky_color.dawn_sky);
1788                         lua_pop(L, 1);
1789
1790                         lua_getfield(L, -1, "dawn_horizon");
1791                         read_color(L, -1, &skybox_params.sky_color.dawn_horizon);
1792                         lua_pop(L, 1);
1793
1794                         lua_getfield(L, -1, "night_sky");
1795                         read_color(L, -1, &skybox_params.sky_color.night_sky);
1796                         lua_pop(L, 1);
1797
1798                         lua_getfield(L, -1, "night_horizon");
1799                         read_color(L, -1, &skybox_params.sky_color.night_horizon);
1800                         lua_pop(L, 1);
1801
1802                         lua_getfield(L, -1, "indoors");
1803                         read_color(L, -1, &skybox_params.sky_color.indoors);
1804                         lua_pop(L, 1);
1805
1806                         // Prevent flickering clouds at dawn/dusk:
1807                         skybox_params.fog_sun_tint = video::SColor(255, 255, 255, 255);
1808                         lua_getfield(L, -1, "fog_sun_tint");
1809                         read_color(L, -1, &skybox_params.fog_sun_tint);
1810                         lua_pop(L, 1);
1811
1812                         skybox_params.fog_moon_tint = video::SColor(255, 255, 255, 255);
1813                         lua_getfield(L, -1, "fog_moon_tint");
1814                         read_color(L, -1, &skybox_params.fog_moon_tint);
1815                         lua_pop(L, 1);
1816
1817                         lua_getfield(L, -1, "fog_tint_type");
1818                         if (!lua_isnil(L, -1))
1819                                 skybox_params.fog_tint_type = luaL_checkstring(L, -1);
1820                         lua_pop(L, 1);
1821
1822                         // Because we need to leave the "sky_color" table.
1823                         lua_pop(L, 1);
1824                 }
1825         } else {
1826                 // Handle old set_sky calls, and log deprecated:
1827                 log_deprecated(L, "Deprecated call to set_sky, please check lua_api.txt");
1828
1829                 // Fix sun, moon and stars showing when classic textured skyboxes are used
1830                 SunParams sun_params = player->getSunParams();
1831                 MoonParams moon_params = player->getMoonParams();
1832                 StarParams star_params = player->getStarParams();
1833
1834                 // Prevent erroneous background colors
1835                 skybox_params.bgcolor = video::SColor(255, 255, 255, 255);
1836                 read_color(L, 2, &skybox_params.bgcolor);
1837
1838                 skybox_params.type = luaL_checkstring(L, 3);
1839
1840                 // Preserve old behaviour of the sun, moon and stars
1841                 // when using the old set_sky call.
1842                 if (skybox_params.type == "regular") {
1843                         sun_params.visible = true;
1844                         sun_params.sunrise_visible = true;
1845                         moon_params.visible = true;
1846                         star_params.visible = true;
1847                 } else {
1848                         sun_params.visible = false;
1849                         sun_params.sunrise_visible = false;
1850                         moon_params.visible = false;
1851                         star_params.visible = false;
1852                 }
1853
1854                 skybox_params.textures.clear();
1855                 if (lua_istable(L, 4)) {
1856                         lua_pushnil(L);
1857                         while (lua_next(L, 4) != 0) {
1858                         // Key at index -2, and value at index -1
1859                                 if (lua_isstring(L, -1))
1860                                         skybox_params.textures.emplace_back(readParam<std::string>(L, -1));
1861                                 else
1862                                         skybox_params.textures.emplace_back("");
1863                                 // Remove the value, keep the key for the next iteration
1864                                 lua_pop(L, 1);
1865                         }
1866                 }
1867                 if (skybox_params.type == "skybox" && skybox_params.textures.size() != 6)
1868                         throw LuaError("Skybox expects 6 textures.");
1869
1870                 skybox_params.clouds = true;
1871                 if (lua_isboolean(L, 5))
1872                         skybox_params.clouds = readParam<bool>(L, 5);
1873
1874                 getServer(L)->setSun(player, sun_params);
1875                 getServer(L)->setMoon(player, moon_params);
1876                 getServer(L)->setStars(player, star_params);
1877         }
1878         getServer(L)->setSky(player, skybox_params);
1879         lua_pushboolean(L, true);
1880         return 1;
1881 }
1882
1883 // get_sky(self)
1884 int ObjectRef::l_get_sky(lua_State *L)
1885 {
1886         NO_MAP_LOCK_REQUIRED;
1887         ObjectRef *ref = checkobject(L, 1);
1888         RemotePlayer *player = getplayer(ref);
1889
1890         if (!player)
1891                 return 0;
1892         SkyboxParams skybox_params;
1893         skybox_params = player->getSkyParams();
1894
1895         push_ARGB8(L, skybox_params.bgcolor);
1896         lua_pushlstring(L, skybox_params.type.c_str(), skybox_params.type.size());
1897
1898         lua_newtable(L);
1899         s16 i = 1;
1900         for (const std::string& texture : skybox_params.textures) {
1901                 lua_pushlstring(L, texture.c_str(), texture.size());
1902                 lua_rawseti(L, -2, i++);
1903         }
1904         lua_pushboolean(L, skybox_params.clouds);
1905         return 4;
1906 }
1907
1908 // get_sky_color(self)
1909 int ObjectRef::l_get_sky_color(lua_State *L)
1910 {
1911         NO_MAP_LOCK_REQUIRED;
1912         ObjectRef *ref = checkobject(L, 1);
1913         RemotePlayer *player = getplayer(ref);
1914
1915         if (!player)
1916                 return 0;
1917
1918         const SkyboxParams& skybox_params = player->getSkyParams();
1919
1920         lua_newtable(L);
1921         if (skybox_params.type == "regular") {
1922                 push_ARGB8(L, skybox_params.sky_color.day_sky);
1923                 lua_setfield(L, -2, "day_sky");
1924                 push_ARGB8(L, skybox_params.sky_color.day_horizon);
1925                 lua_setfield(L, -2, "day_horizon");
1926                 push_ARGB8(L, skybox_params.sky_color.dawn_sky);
1927                 lua_setfield(L, -2, "dawn_sky");
1928                 push_ARGB8(L, skybox_params.sky_color.dawn_horizon);
1929                 lua_setfield(L, -2, "dawn_horizon");
1930                 push_ARGB8(L, skybox_params.sky_color.night_sky);
1931                 lua_setfield(L, -2, "night_sky");
1932                 push_ARGB8(L, skybox_params.sky_color.night_horizon);
1933                 lua_setfield(L, -2, "night_horizon");
1934                 push_ARGB8(L, skybox_params.sky_color.indoors);
1935                 lua_setfield(L, -2, "indoors");
1936         }
1937         push_ARGB8(L, skybox_params.fog_sun_tint);
1938         lua_setfield(L, -2, "fog_sun_tint");
1939         push_ARGB8(L, skybox_params.fog_moon_tint);
1940         lua_setfield(L, -2, "fog_moon_tint");
1941         lua_pushstring(L, skybox_params.fog_tint_type.c_str());
1942         lua_setfield(L, -2, "fog_tint_type");
1943         return 1;
1944 }
1945
1946 // set_sun(self, {visible, texture=, tonemap=, sunrise=, rotation=, scale=})
1947 int ObjectRef::l_set_sun(lua_State *L)
1948 {
1949         NO_MAP_LOCK_REQUIRED;
1950         ObjectRef *ref = checkobject(L, 1);
1951         RemotePlayer *player = getplayer(ref);
1952         if (!player)
1953                 return 0;
1954
1955         if (!lua_istable(L, 2))
1956                 return 0;
1957
1958         SunParams sun_params = player->getSunParams();
1959
1960         sun_params.visible = getboolfield_default(L, 2,
1961                         "visible", sun_params.visible);
1962         sun_params.texture = getstringfield_default(L, 2,
1963                         "texture", sun_params.texture);
1964         sun_params.tonemap = getstringfield_default(L, 2,
1965                         "tonemap", sun_params.tonemap);
1966         sun_params.sunrise = getstringfield_default(L, 2,
1967                         "sunrise", sun_params.sunrise);
1968         sun_params.sunrise_visible = getboolfield_default(L, 2,
1969                         "sunrise_visible", sun_params.sunrise_visible);
1970         sun_params.scale = getfloatfield_default(L, 2,
1971                         "scale", sun_params.scale);
1972
1973         getServer(L)->setSun(player, sun_params);
1974         lua_pushboolean(L, true);
1975         return 1;
1976 }
1977
1978 //get_sun(self)
1979 int ObjectRef::l_get_sun(lua_State *L)
1980 {
1981         NO_MAP_LOCK_REQUIRED;
1982         ObjectRef *ref = checkobject(L, 1);
1983         RemotePlayer *player = getplayer(ref);
1984         if (!player)
1985                 return 0;
1986         const SunParams &sun_params = player->getSunParams();
1987
1988         lua_newtable(L);
1989         lua_pushboolean(L, sun_params.visible);
1990         lua_setfield(L, -2, "visible");
1991         lua_pushstring(L, sun_params.texture.c_str());
1992         lua_setfield(L, -2, "texture");
1993         lua_pushstring(L, sun_params.tonemap.c_str());
1994         lua_setfield(L, -2, "tonemap");
1995         lua_pushstring(L, sun_params.sunrise.c_str());
1996         lua_setfield(L, -2, "sunrise");
1997         lua_pushboolean(L, sun_params.sunrise_visible);
1998         lua_setfield(L, -2, "sunrise_visible");
1999         lua_pushnumber(L, sun_params.scale);
2000         lua_setfield(L, -2, "scale");
2001
2002         return 1;
2003 }
2004
2005 // set_moon(self, {visible, texture=, tonemap=, sunrise=, rotation=, scale=})
2006 int ObjectRef::l_set_moon(lua_State *L)
2007 {
2008         NO_MAP_LOCK_REQUIRED;
2009         ObjectRef *ref = checkobject(L, 1);
2010         RemotePlayer *player = getplayer(ref);
2011         if (!player)
2012                 return 0;
2013         if (!lua_istable(L, 2))
2014                 return 0;
2015
2016         MoonParams moon_params = player->getMoonParams();
2017
2018         moon_params.visible = getboolfield_default(L, 2,
2019                 "visible", moon_params.visible);
2020         moon_params.texture = getstringfield_default(L, 2,
2021                 "texture", moon_params.texture);
2022         moon_params.tonemap = getstringfield_default(L, 2,
2023                 "tonemap", moon_params.tonemap);
2024         moon_params.scale = getfloatfield_default(L, 2,
2025                 "scale", moon_params.scale);
2026
2027         getServer(L)->setMoon(player, moon_params);
2028         lua_pushboolean(L, true);
2029         return 1;
2030 }
2031
2032 // get_moon(self)
2033 int ObjectRef::l_get_moon(lua_State *L)
2034 {
2035         NO_MAP_LOCK_REQUIRED;
2036         ObjectRef *ref = checkobject(L, 1);
2037         RemotePlayer *player = getplayer(ref);
2038         if (!player)
2039                 return 0;
2040         const MoonParams &moon_params = player->getMoonParams();
2041
2042         lua_newtable(L);
2043         lua_pushboolean(L, moon_params.visible);
2044         lua_setfield(L, -2, "visible");
2045         lua_pushstring(L, moon_params.texture.c_str());
2046         lua_setfield(L, -2, "texture");
2047         lua_pushstring(L, moon_params.tonemap.c_str());
2048         lua_setfield(L, -2, "tonemap");
2049         lua_pushnumber(L, moon_params.scale);
2050         lua_setfield(L, -2, "scale");
2051
2052         return 1;
2053 }
2054
2055 // set_stars(self, {visible, count=, starcolor=, rotation=, scale=})
2056 int ObjectRef::l_set_stars(lua_State *L)
2057 {
2058         NO_MAP_LOCK_REQUIRED;
2059         ObjectRef *ref = checkobject(L, 1);
2060         RemotePlayer *player = getplayer(ref);
2061         if (!player)
2062                 return 0;
2063         if (!lua_istable(L, 2))
2064                 return 0;
2065
2066         StarParams star_params = player->getStarParams();
2067
2068         star_params.visible = getboolfield_default(L, 2,
2069                 "visible", star_params.visible);
2070         star_params.count = getintfield_default(L, 2,
2071                 "count", star_params.count);
2072
2073         lua_getfield(L, 2, "star_color");
2074         if (!lua_isnil(L, -1))
2075                 read_color(L, -1, &star_params.starcolor);
2076         lua_pop(L, 1);
2077
2078         star_params.scale = getfloatfield_default(L, 2,
2079                 "scale", star_params.scale);
2080
2081         getServer(L)->setStars(player, star_params);
2082         lua_pushboolean(L, true);
2083         return 1;
2084 }
2085
2086 // get_stars(self)
2087 int ObjectRef::l_get_stars(lua_State *L)
2088 {
2089         NO_MAP_LOCK_REQUIRED;
2090         ObjectRef *ref = checkobject(L, 1);
2091         RemotePlayer *player = getplayer(ref);
2092         if (!player)
2093                 return 0;
2094         const StarParams &star_params = player->getStarParams();
2095
2096         lua_newtable(L);
2097         lua_pushboolean(L, star_params.visible);
2098         lua_setfield(L, -2, "visible");
2099         lua_pushnumber(L, star_params.count);
2100         lua_setfield(L, -2, "count");
2101         push_ARGB8(L, star_params.starcolor);
2102         lua_setfield(L, -2, "star_color");
2103         lua_pushnumber(L, star_params.scale);
2104         lua_setfield(L, -2, "scale");
2105
2106         return 1;
2107 }
2108
2109 // set_clouds(self, {density=, color=, ambient=, height=, thickness=, speed=})
2110 int ObjectRef::l_set_clouds(lua_State *L)
2111 {
2112         NO_MAP_LOCK_REQUIRED;
2113         ObjectRef *ref = checkobject(L, 1);
2114         RemotePlayer *player = getplayer(ref);
2115         if (!player)
2116                 return 0;
2117         if (!lua_istable(L, 2))
2118                 return 0;
2119
2120         CloudParams cloud_params = player->getCloudParams();
2121
2122         cloud_params.density = getfloatfield_default(L, 2, "density", cloud_params.density);
2123
2124         lua_getfield(L, 2, "color");
2125         if (!lua_isnil(L, -1))
2126                 read_color(L, -1, &cloud_params.color_bright);
2127         lua_pop(L, 1);
2128         lua_getfield(L, 2, "ambient");
2129         if (!lua_isnil(L, -1))
2130                 read_color(L, -1, &cloud_params.color_ambient);
2131         lua_pop(L, 1);
2132
2133         cloud_params.height    = getfloatfield_default(L, 2, "height",    cloud_params.height   );
2134         cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness);
2135
2136         lua_getfield(L, 2, "speed");
2137         if (lua_istable(L, -1)) {
2138                 v2f new_speed;
2139                 new_speed.X = getfloatfield_default(L, -1, "x", 0);
2140                 new_speed.Y = getfloatfield_default(L, -1, "z", 0);
2141                 cloud_params.speed = new_speed;
2142         }
2143         lua_pop(L, 1);
2144
2145         getServer(L)->setClouds(player, cloud_params);
2146         lua_pushboolean(L, true);
2147         return 1;
2148 }
2149
2150 int ObjectRef::l_get_clouds(lua_State *L)
2151 {
2152         NO_MAP_LOCK_REQUIRED;
2153         ObjectRef *ref = checkobject(L, 1);
2154         RemotePlayer *player = getplayer(ref);
2155         if (!player)
2156                 return 0;
2157         const CloudParams &cloud_params = player->getCloudParams();
2158
2159         lua_newtable(L);
2160         lua_pushnumber(L, cloud_params.density);
2161         lua_setfield(L, -2, "density");
2162         push_ARGB8(L, cloud_params.color_bright);
2163         lua_setfield(L, -2, "color");
2164         push_ARGB8(L, cloud_params.color_ambient);
2165         lua_setfield(L, -2, "ambient");
2166         lua_pushnumber(L, cloud_params.height);
2167         lua_setfield(L, -2, "height");
2168         lua_pushnumber(L, cloud_params.thickness);
2169         lua_setfield(L, -2, "thickness");
2170         lua_newtable(L);
2171         lua_pushnumber(L, cloud_params.speed.X);
2172         lua_setfield(L, -2, "x");
2173         lua_pushnumber(L, cloud_params.speed.Y);
2174         lua_setfield(L, -2, "y");
2175         lua_setfield(L, -2, "speed");
2176
2177         return 1;
2178 }
2179
2180
2181 // override_day_night_ratio(self, brightness=0...1)
2182 int ObjectRef::l_override_day_night_ratio(lua_State *L)
2183 {
2184         NO_MAP_LOCK_REQUIRED;
2185         ObjectRef *ref = checkobject(L, 1);
2186         RemotePlayer *player = getplayer(ref);
2187         if (player == NULL)
2188                 return 0;
2189
2190         bool do_override = false;
2191         float ratio = 0.0f;
2192         if (!lua_isnil(L, 2)) {
2193                 do_override = true;
2194                 ratio = readParam<float>(L, 2);
2195         }
2196
2197         getServer(L)->overrideDayNightRatio(player, do_override, ratio);
2198         lua_pushboolean(L, true);
2199         return 1;
2200 }
2201
2202 // get_day_night_ratio(self)
2203 int ObjectRef::l_get_day_night_ratio(lua_State *L)
2204 {
2205         NO_MAP_LOCK_REQUIRED;
2206         ObjectRef *ref = checkobject(L, 1);
2207         RemotePlayer *player = getplayer(ref);
2208         if (player == NULL)
2209                 return 0;
2210
2211         bool do_override;
2212         float ratio;
2213         player->getDayNightRatio(&do_override, &ratio);
2214
2215         if (do_override)
2216                 lua_pushnumber(L, ratio);
2217         else
2218                 lua_pushnil(L);
2219
2220         return 1;
2221 }
2222
2223 // set_minimap_modes(self, modes, modeindex)
2224 int ObjectRef::l_set_minimap_modes(lua_State *L)
2225 {
2226         NO_MAP_LOCK_REQUIRED;
2227
2228         // Arg 1 should be a player
2229         ObjectRef *ref = checkobject(L, 1);
2230         RemotePlayer *player = getplayer(ref);
2231         if (player == NULL)
2232                 return 0;
2233
2234         // Arg 2 should be a table (of tables)
2235         if (!lua_istable(L, 2)) {
2236                 return 0;
2237         }
2238
2239         // Arg 3 should be a number
2240         s16 wantedmode = lua_tonumber(L, 3);
2241
2242         std::vector<MinimapMode> modes;
2243
2244         lua_pushnil(L);
2245         while (lua_next(L, 2) != 0) {
2246                 /* key is at index -2, value is at index -1 */
2247                 if (lua_istable(L, -1)) {
2248                         bool ok = true;
2249                         MinimapMode mode;
2250                         std::string type = getstringfield_default(L, -1, "type", "");
2251                         if (type == "off")
2252                                 mode.type = MINIMAP_TYPE_OFF;
2253                         else if (type == "surface")
2254                                 mode.type = MINIMAP_TYPE_SURFACE;
2255                         else if (type == "radar")
2256                                 mode.type = MINIMAP_TYPE_RADAR;
2257                         else if (type == "texture") {
2258                                 mode.type = MINIMAP_TYPE_TEXTURE;
2259                                 mode.texture = getstringfield_default(L, -1, "texture", "");
2260                                 mode.scale = getintfield_default(L, -1, "scale", 1);
2261                         } else {
2262                                 warningstream << "Minimap mode of unknown type \"" << type.c_str()
2263                                         << "\" ignored.\n" << std::endl;
2264                                 ok = false;
2265                         }
2266
2267                         if (ok) {
2268                                 mode.label = getstringfield_default(L, -1, "label", "");
2269                                 // Size is limited to 512. Performance gets poor if size too large, and
2270                                 // segfaults have been experienced.
2271                                 mode.size = rangelim(getintfield_default(L, -1, "size", 0), 1, 512);
2272                                 modes.push_back(mode);
2273                         }
2274                 }
2275                 /* removes 'value'; keeps 'key' for next iteration */
2276                 lua_pop(L, 1);
2277         }
2278         lua_pop(L, 1); // Remove key
2279
2280         getServer(L)->SendMinimapModes(player->getPeerId(), modes, wantedmode);
2281         return 0;
2282 }
2283
2284 ObjectRef::ObjectRef(ServerActiveObject *object):
2285         m_object(object)
2286 {
2287         //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
2288 }
2289
2290 // Creates an ObjectRef and leaves it on top of stack
2291 // Not callable from Lua; all references are created on the C side.
2292 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
2293 {
2294         ObjectRef *o = new ObjectRef(object);
2295         //infostream<<"ObjectRef::create: o="<<o<<std::endl;
2296         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2297         luaL_getmetatable(L, className);
2298         lua_setmetatable(L, -2);
2299 }
2300
2301 void ObjectRef::set_null(lua_State *L)
2302 {
2303         ObjectRef *o = checkobject(L, -1);
2304         o->m_object = NULL;
2305 }
2306
2307 void ObjectRef::Register(lua_State *L)
2308 {
2309         lua_newtable(L);
2310         int methodtable = lua_gettop(L);
2311         luaL_newmetatable(L, className);
2312         int metatable = lua_gettop(L);
2313
2314         lua_pushliteral(L, "__metatable");
2315         lua_pushvalue(L, methodtable);
2316         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
2317
2318         lua_pushliteral(L, "__index");
2319         lua_pushvalue(L, methodtable);
2320         lua_settable(L, metatable);
2321
2322         lua_pushliteral(L, "__gc");
2323         lua_pushcfunction(L, gc_object);
2324         lua_settable(L, metatable);
2325
2326         lua_pop(L, 1);  // drop metatable
2327
2328         markAliasDeprecated(methods);
2329         luaL_openlib(L, 0, methods, 0);  // fill methodtable
2330         lua_pop(L, 1);  // drop methodtable
2331
2332         // Cannot be created from Lua
2333         //lua_register(L, className, create_object);
2334 }
2335
2336 const char ObjectRef::className[] = "ObjectRef";
2337 luaL_Reg ObjectRef::methods[] = {
2338         // ServerActiveObject
2339         luamethod(ObjectRef, remove),
2340         luamethod_aliased(ObjectRef, get_pos, getpos),
2341         luamethod_aliased(ObjectRef, set_pos, setpos),
2342         luamethod_aliased(ObjectRef, move_to, moveto),
2343         luamethod(ObjectRef, punch),
2344         luamethod(ObjectRef, right_click),
2345         luamethod(ObjectRef, set_hp),
2346         luamethod(ObjectRef, get_hp),
2347         luamethod(ObjectRef, get_inventory),
2348         luamethod(ObjectRef, get_wield_list),
2349         luamethod(ObjectRef, get_wield_index),
2350         luamethod(ObjectRef, get_wielded_item),
2351         luamethod(ObjectRef, set_wielded_item),
2352         luamethod(ObjectRef, set_armor_groups),
2353         luamethod(ObjectRef, get_armor_groups),
2354         luamethod(ObjectRef, set_animation),
2355         luamethod(ObjectRef, get_animation),
2356         luamethod(ObjectRef, set_animation_frame_speed),
2357         luamethod(ObjectRef, set_bone_position),
2358         luamethod(ObjectRef, get_bone_position),
2359         luamethod(ObjectRef, set_attach),
2360         luamethod(ObjectRef, get_attach),
2361         luamethod(ObjectRef, get_children),
2362         luamethod(ObjectRef, set_detach),
2363         luamethod(ObjectRef, set_properties),
2364         luamethod(ObjectRef, get_properties),
2365         luamethod(ObjectRef, set_nametag_attributes),
2366         luamethod(ObjectRef, get_nametag_attributes),
2367
2368         luamethod_aliased(ObjectRef, set_velocity, setvelocity),
2369         luamethod(ObjectRef, add_velocity),
2370         {"add_player_velocity", ObjectRef::l_add_velocity},
2371         luamethod_aliased(ObjectRef, get_velocity, getvelocity),
2372         {"get_player_velocity", ObjectRef::l_get_velocity},
2373
2374         // LuaEntitySAO-only
2375         luamethod_aliased(ObjectRef, set_acceleration, setacceleration),
2376         luamethod_aliased(ObjectRef, get_acceleration, getacceleration),
2377         luamethod_aliased(ObjectRef, set_yaw, setyaw),
2378         luamethod_aliased(ObjectRef, get_yaw, getyaw),
2379         luamethod(ObjectRef, set_rotation),
2380         luamethod(ObjectRef, get_rotation),
2381         luamethod_aliased(ObjectRef, set_texture_mod, settexturemod),
2382         luamethod(ObjectRef, get_texture_mod),
2383         luamethod_aliased(ObjectRef, set_sprite, setsprite),
2384         luamethod(ObjectRef, get_entity_name),
2385         luamethod(ObjectRef, get_luaentity),
2386         // Player-only
2387         luamethod(ObjectRef, is_player),
2388         luamethod(ObjectRef, is_player_connected),
2389         luamethod(ObjectRef, get_player_name),
2390
2391         luamethod(ObjectRef, get_look_dir),
2392         luamethod(ObjectRef, get_look_pitch),
2393         luamethod(ObjectRef, get_look_yaw),
2394         luamethod(ObjectRef, get_look_vertical),
2395         luamethod(ObjectRef, get_look_horizontal),
2396         luamethod(ObjectRef, set_look_horizontal),
2397         luamethod(ObjectRef, set_look_vertical),
2398         luamethod(ObjectRef, set_look_yaw),
2399         luamethod(ObjectRef, set_look_pitch),
2400         luamethod(ObjectRef, get_fov),
2401         luamethod(ObjectRef, set_fov),
2402         luamethod(ObjectRef, get_breath),
2403         luamethod(ObjectRef, set_breath),
2404         luamethod(ObjectRef, get_attribute),
2405         luamethod(ObjectRef, set_attribute),
2406         luamethod(ObjectRef, get_meta),
2407         luamethod(ObjectRef, set_inventory_formspec),
2408         luamethod(ObjectRef, get_inventory_formspec),
2409         luamethod(ObjectRef, set_formspec_prepend),
2410         luamethod(ObjectRef, get_formspec_prepend),
2411         luamethod(ObjectRef, get_player_control),
2412         luamethod(ObjectRef, get_player_control_bits),
2413         luamethod(ObjectRef, set_physics_override),
2414         luamethod(ObjectRef, get_physics_override),
2415         luamethod(ObjectRef, hud_add),
2416         luamethod(ObjectRef, hud_remove),
2417         luamethod(ObjectRef, hud_change),
2418         luamethod(ObjectRef, hud_get),
2419         luamethod(ObjectRef, hud_set_flags),
2420         luamethod(ObjectRef, hud_get_flags),
2421         luamethod(ObjectRef, hud_set_hotbar_itemcount),
2422         luamethod(ObjectRef, hud_get_hotbar_itemcount),
2423         luamethod(ObjectRef, hud_set_hotbar_image),
2424         luamethod(ObjectRef, hud_get_hotbar_image),
2425         luamethod(ObjectRef, hud_set_hotbar_selected_image),
2426         luamethod(ObjectRef, hud_get_hotbar_selected_image),
2427         luamethod(ObjectRef, set_sky),
2428         luamethod(ObjectRef, get_sky),
2429         luamethod(ObjectRef, get_sky_color),
2430         luamethod(ObjectRef, set_sun),
2431         luamethod(ObjectRef, get_sun),
2432         luamethod(ObjectRef, set_moon),
2433         luamethod(ObjectRef, get_moon),
2434         luamethod(ObjectRef, set_stars),
2435         luamethod(ObjectRef, get_stars),
2436         luamethod(ObjectRef, set_clouds),
2437         luamethod(ObjectRef, get_clouds),
2438         luamethod(ObjectRef, override_day_night_ratio),
2439         luamethod(ObjectRef, get_day_night_ratio),
2440         luamethod(ObjectRef, set_local_animation),
2441         luamethod(ObjectRef, get_local_animation),
2442         luamethod(ObjectRef, set_eye_offset),
2443         luamethod(ObjectRef, get_eye_offset),
2444         luamethod(ObjectRef, send_mapblock),
2445         luamethod(ObjectRef, set_minimap_modes),
2446         {0,0}
2447 };