]> git.lizzy.rs Git - minetest.git/blob - src/script/lua_api/l_object.cpp
24667e7696154023b66c0eb5607505adf07fd684
[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 "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)
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         co->getAttachment(&parent_id, &bone, &position, &rotation);
691         if (parent_id) {
692                 ServerActiveObject *old_parent = env->getActiveObject(parent_id);
693                 old_parent->removeAttachmentChild(co->getId());
694         }
695
696         bone = "";
697         if (!lua_isnil(L, 3))
698                 bone = readParam<std::string>(L, 3);
699         position = v3f(0, 0, 0);
700         if (!lua_isnil(L, 4))
701                 position = read_v3f(L, 4);
702         rotation = v3f(0, 0, 0);
703         if (!lua_isnil(L, 5))
704                 rotation = read_v3f(L, 5);
705         co->setAttachment(parent->getId(), bone, position, rotation);
706         parent->addAttachmentChild(co->getId());
707         return 0;
708 }
709
710 // get_attach(self)
711 int ObjectRef::l_get_attach(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         // Do it
721         int parent_id = 0;
722         std::string bone;
723         v3f position = v3f(0, 0, 0);
724         v3f rotation = v3f(0, 0, 0);
725         co->getAttachment(&parent_id, &bone, &position, &rotation);
726         if (!parent_id)
727                 return 0;
728         ServerActiveObject *parent = env->getActiveObject(parent_id);
729
730         getScriptApiBase(L)->objectrefGetOrCreate(L, parent);
731         lua_pushlstring(L, bone.c_str(), bone.size());
732         push_v3f(L, position);
733         push_v3f(L, rotation);
734         return 4;
735 }
736
737 // set_detach(self)
738 int ObjectRef::l_set_detach(lua_State *L)
739 {
740         GET_ENV_PTR;
741
742         ObjectRef *ref = checkobject(L, 1);
743         ServerActiveObject *co = getobject(ref);
744         if (co == NULL)
745                 return 0;
746
747         co->clearParentAttachment();
748         return 0;
749 }
750
751 // set_properties(self, properties)
752 int ObjectRef::l_set_properties(lua_State *L)
753 {
754         NO_MAP_LOCK_REQUIRED;
755         ObjectRef *ref = checkobject(L, 1);
756         ServerActiveObject *co = getobject(ref);
757         if (!co)
758                 return 0;
759
760         ObjectProperties *prop = co->accessObjectProperties();
761         if (!prop)
762                 return 0;
763
764         read_object_properties(L, 2, co, prop, getServer(L)->idef());
765         co->notifyObjectPropertiesModified();
766         return 0;
767 }
768
769 // get_properties(self)
770 int ObjectRef::l_get_properties(lua_State *L)
771 {
772         NO_MAP_LOCK_REQUIRED;
773         ObjectRef *ref = checkobject(L, 1);
774         ServerActiveObject *co = getobject(ref);
775         if (co == NULL)
776                 return 0;
777         ObjectProperties *prop = co->accessObjectProperties();
778         if (!prop)
779                 return 0;
780         push_object_properties(L, prop);
781         return 1;
782 }
783
784 // is_player(self)
785 int ObjectRef::l_is_player(lua_State *L)
786 {
787         NO_MAP_LOCK_REQUIRED;
788         ObjectRef *ref = checkobject(L, 1);
789         RemotePlayer *player = getplayer(ref);
790         lua_pushboolean(L, (player != NULL));
791         return 1;
792 }
793
794 // set_nametag_attributes(self, attributes)
795 int ObjectRef::l_set_nametag_attributes(lua_State *L)
796 {
797         NO_MAP_LOCK_REQUIRED;
798         ObjectRef *ref = checkobject(L, 1);
799         ServerActiveObject *co = getobject(ref);
800
801         if (co == NULL)
802                 return 0;
803         ObjectProperties *prop = co->accessObjectProperties();
804         if (!prop)
805                 return 0;
806
807         lua_getfield(L, 2, "color");
808         if (!lua_isnil(L, -1)) {
809                 video::SColor color = prop->nametag_color;
810                 read_color(L, -1, &color);
811                 prop->nametag_color = color;
812         }
813         lua_pop(L, 1);
814
815         std::string nametag = getstringfield_default(L, 2, "text", "");
816         prop->nametag = nametag;
817
818         co->notifyObjectPropertiesModified();
819         lua_pushboolean(L, true);
820         return 1;
821 }
822
823 // get_nametag_attributes(self)
824 int ObjectRef::l_get_nametag_attributes(lua_State *L)
825 {
826         NO_MAP_LOCK_REQUIRED;
827         ObjectRef *ref = checkobject(L, 1);
828         ServerActiveObject *co = getobject(ref);
829
830         if (co == NULL)
831                 return 0;
832         ObjectProperties *prop = co->accessObjectProperties();
833         if (!prop)
834                 return 0;
835
836         video::SColor color = prop->nametag_color;
837
838         lua_newtable(L);
839         push_ARGB8(L, color);
840         lua_setfield(L, -2, "color");
841         lua_pushstring(L, prop->nametag.c_str());
842         lua_setfield(L, -2, "text");
843         return 1;
844 }
845
846 /* LuaEntitySAO-only */
847
848 // set_velocity(self, {x=num, y=num, z=num})
849 int ObjectRef::l_set_velocity(lua_State *L)
850 {
851         NO_MAP_LOCK_REQUIRED;
852         ObjectRef *ref = checkobject(L, 1);
853         LuaEntitySAO *co = getluaobject(ref);
854         if (co == NULL) return 0;
855         v3f pos = checkFloatPos(L, 2);
856         // Do it
857         co->setVelocity(pos);
858         return 0;
859 }
860
861 // add_velocity(self, {x=num, y=num, z=num})
862 int ObjectRef::l_add_velocity(lua_State *L)
863 {
864         NO_MAP_LOCK_REQUIRED;
865         ObjectRef *ref = checkobject(L, 1);
866         LuaEntitySAO *co = getluaobject(ref);
867         if (!co)
868                 return 0;
869         v3f pos = checkFloatPos(L, 2);
870         // Do it
871         co->addVelocity(pos);
872         return 0;
873 }
874
875 // get_velocity(self)
876 int ObjectRef::l_get_velocity(lua_State *L)
877 {
878         NO_MAP_LOCK_REQUIRED;
879         ObjectRef *ref = checkobject(L, 1);
880         LuaEntitySAO *co = getluaobject(ref);
881         if (co == NULL) return 0;
882         // Do it
883         v3f v = co->getVelocity();
884         pushFloatPos(L, v);
885         return 1;
886 }
887
888 // set_acceleration(self, {x=num, y=num, z=num})
889 int ObjectRef::l_set_acceleration(lua_State *L)
890 {
891         NO_MAP_LOCK_REQUIRED;
892         ObjectRef *ref = checkobject(L, 1);
893         LuaEntitySAO *co = getluaobject(ref);
894         if (co == NULL) return 0;
895         // pos
896         v3f pos = checkFloatPos(L, 2);
897         // Do it
898         co->setAcceleration(pos);
899         return 0;
900 }
901
902 // get_acceleration(self)
903 int ObjectRef::l_get_acceleration(lua_State *L)
904 {
905         NO_MAP_LOCK_REQUIRED;
906         ObjectRef *ref = checkobject(L, 1);
907         LuaEntitySAO *co = getluaobject(ref);
908         if (co == NULL) return 0;
909         // Do it
910         v3f v = co->getAcceleration();
911         pushFloatPos(L, v);
912         return 1;
913 }
914
915 // set_rotation(self, {x=num, y=num, z=num})
916 // Each 'num' is in radians
917 int ObjectRef::l_set_rotation(lua_State *L)
918 {
919         NO_MAP_LOCK_REQUIRED;
920         ObjectRef *ref = checkobject(L, 1);
921         LuaEntitySAO *co = getluaobject(ref);
922         if (!co)
923                 return 0;
924
925         v3f rotation = check_v3f(L, 2) * core::RADTODEG;
926         co->setRotation(rotation);
927         return 0;
928 }
929
930 // get_rotation(self)
931 // returns: {x=num, y=num, z=num}
932 // Each 'num' is in radians
933 int ObjectRef::l_get_rotation(lua_State *L)
934 {
935         NO_MAP_LOCK_REQUIRED;
936         ObjectRef *ref = checkobject(L, 1);
937         LuaEntitySAO *co = getluaobject(ref);
938         if (!co)
939                 return 0;
940
941         lua_newtable(L);
942         v3f rotation = co->getRotation() * core::DEGTORAD;
943         push_v3f(L, rotation);
944         return 1;
945 }
946
947 // set_yaw(self, radians)
948 int ObjectRef::l_set_yaw(lua_State *L)
949 {
950         NO_MAP_LOCK_REQUIRED;
951         ObjectRef *ref = checkobject(L, 1);
952         LuaEntitySAO *co = getluaobject(ref);
953
954         if (co == NULL) return 0;
955         if (isNaN(L, 2))
956                 throw LuaError("ObjectRef::set_yaw: NaN value is not allowed.");
957
958         float yaw = readParam<float>(L, 2) * core::RADTODEG;
959         co->setRotation(v3f(0, yaw, 0));
960         return 0;
961 }
962
963 // get_yaw(self)
964 int ObjectRef::l_get_yaw(lua_State *L)
965 {
966         NO_MAP_LOCK_REQUIRED;
967         ObjectRef *ref = checkobject(L, 1);
968         LuaEntitySAO *co = getluaobject(ref);
969         if (!co)
970                 return 0;
971
972         float yaw = co->getRotation().Y * core::DEGTORAD;
973         lua_pushnumber(L, yaw);
974         return 1;
975 }
976
977 // set_texture_mod(self, mod)
978 int ObjectRef::l_set_texture_mod(lua_State *L)
979 {
980         NO_MAP_LOCK_REQUIRED;
981         ObjectRef *ref = checkobject(L, 1);
982         LuaEntitySAO *co = getluaobject(ref);
983         if (co == NULL) return 0;
984         // Do it
985         std::string mod = luaL_checkstring(L, 2);
986         co->setTextureMod(mod);
987         return 0;
988 }
989
990 // get_texture_mod(self)
991 int ObjectRef::l_get_texture_mod(lua_State *L)
992 {
993         NO_MAP_LOCK_REQUIRED;
994         ObjectRef *ref = checkobject(L, 1);
995         LuaEntitySAO *co = getluaobject(ref);
996         if (co == NULL) return 0;
997         // Do it
998         std::string mod = co->getTextureMod();
999         lua_pushstring(L, mod.c_str());
1000         return 1;
1001 }
1002
1003 // set_sprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
1004 //           select_horiz_by_yawpitch=false)
1005 int ObjectRef::l_set_sprite(lua_State *L)
1006 {
1007         NO_MAP_LOCK_REQUIRED;
1008         ObjectRef *ref = checkobject(L, 1);
1009         LuaEntitySAO *co = getluaobject(ref);
1010         if (co == NULL) return 0;
1011         // Do it
1012         v2s16 p(0,0);
1013         if (!lua_isnil(L, 2))
1014                 p = readParam<v2s16>(L, 2);
1015         int num_frames = 1;
1016         if (!lua_isnil(L, 3))
1017                 num_frames = lua_tonumber(L, 3);
1018         float framelength = 0.2;
1019         if (!lua_isnil(L, 4))
1020                 framelength = lua_tonumber(L, 4);
1021         bool select_horiz_by_yawpitch = false;
1022         if (!lua_isnil(L, 5))
1023                 select_horiz_by_yawpitch = readParam<bool>(L, 5);
1024         co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
1025         return 0;
1026 }
1027
1028 // DEPRECATED
1029 // get_entity_name(self)
1030 int ObjectRef::l_get_entity_name(lua_State *L)
1031 {
1032         NO_MAP_LOCK_REQUIRED;
1033         ObjectRef *ref = checkobject(L, 1);
1034         LuaEntitySAO *co = getluaobject(ref);
1035         log_deprecated(L,"Deprecated call to \"get_entity_name");
1036         if (co == NULL) return 0;
1037         // Do it
1038         std::string name = co->getName();
1039         lua_pushstring(L, name.c_str());
1040         return 1;
1041 }
1042
1043 // get_luaentity(self)
1044 int ObjectRef::l_get_luaentity(lua_State *L)
1045 {
1046         NO_MAP_LOCK_REQUIRED;
1047         ObjectRef *ref = checkobject(L, 1);
1048         LuaEntitySAO *co = getluaobject(ref);
1049         if (co == NULL) return 0;
1050         // Do it
1051         luaentity_get(L, co->getId());
1052         return 1;
1053 }
1054
1055 /* Player-only */
1056
1057 // is_player_connected(self)
1058 int ObjectRef::l_is_player_connected(lua_State *L)
1059 {
1060         NO_MAP_LOCK_REQUIRED;
1061         // This method was once added for a bugfix, but never documented
1062         log_deprecated(L, "is_player_connected is undocumented and "
1063                 "will be removed in a future release");
1064         ObjectRef *ref = checkobject(L, 1);
1065         RemotePlayer *player = getplayer(ref);
1066         lua_pushboolean(L, (player != NULL && player->getPeerId() != PEER_ID_INEXISTENT));
1067         return 1;
1068 }
1069
1070 // get_player_name(self)
1071 int ObjectRef::l_get_player_name(lua_State *L)
1072 {
1073         NO_MAP_LOCK_REQUIRED;
1074         ObjectRef *ref = checkobject(L, 1);
1075         RemotePlayer *player = getplayer(ref);
1076         if (player == NULL) {
1077                 lua_pushlstring(L, "", 0);
1078                 return 1;
1079         }
1080         // Do it
1081         lua_pushstring(L, player->getName());
1082         return 1;
1083 }
1084
1085 // get_player_velocity(self)
1086 int ObjectRef::l_get_player_velocity(lua_State *L)
1087 {
1088         NO_MAP_LOCK_REQUIRED;
1089         ObjectRef *ref = checkobject(L, 1);
1090         RemotePlayer *player = getplayer(ref);
1091         if (player == NULL) {
1092                 lua_pushnil(L);
1093                 return 1;
1094         }
1095         // Do it
1096         push_v3f(L, player->getSpeed() / BS);
1097         return 1;
1098 }
1099
1100 // add_player_velocity(self, {x=num, y=num, z=num})
1101 int ObjectRef::l_add_player_velocity(lua_State *L)
1102 {
1103         NO_MAP_LOCK_REQUIRED;
1104         ObjectRef *ref = checkobject(L, 1);
1105         v3f vel = checkFloatPos(L, 2);
1106
1107         PlayerSAO *co = getplayersao(ref);
1108         if (!co)
1109                 return 0;
1110
1111         // Do it
1112         co->setMaxSpeedOverride(vel);
1113         getServer(L)->SendPlayerSpeed(co->getPeerID(), vel);
1114         return 0;
1115 }
1116
1117 // get_look_dir(self)
1118 int ObjectRef::l_get_look_dir(lua_State *L)
1119 {
1120         NO_MAP_LOCK_REQUIRED;
1121         ObjectRef *ref = checkobject(L, 1);
1122         PlayerSAO* co = getplayersao(ref);
1123         if (co == NULL) return 0;
1124         // Do it
1125         float pitch = co->getRadLookPitchDep();
1126         float yaw = co->getRadYawDep();
1127         v3f v(std::cos(pitch) * std::cos(yaw), std::sin(pitch), std::cos(pitch) *
1128                 std::sin(yaw));
1129         push_v3f(L, v);
1130         return 1;
1131 }
1132
1133 // DEPRECATED
1134 // get_look_pitch(self)
1135 int ObjectRef::l_get_look_pitch(lua_State *L)
1136 {
1137         NO_MAP_LOCK_REQUIRED;
1138
1139         log_deprecated(L,
1140                 "Deprecated call to get_look_pitch, use get_look_vertical instead");
1141
1142         ObjectRef *ref = checkobject(L, 1);
1143         PlayerSAO* co = getplayersao(ref);
1144         if (co == NULL) return 0;
1145         // Do it
1146         lua_pushnumber(L, co->getRadLookPitchDep());
1147         return 1;
1148 }
1149
1150 // DEPRECATED
1151 // get_look_yaw(self)
1152 int ObjectRef::l_get_look_yaw(lua_State *L)
1153 {
1154         NO_MAP_LOCK_REQUIRED;
1155
1156         log_deprecated(L,
1157                 "Deprecated call to get_look_yaw, use get_look_horizontal instead");
1158
1159         ObjectRef *ref = checkobject(L, 1);
1160         PlayerSAO* co = getplayersao(ref);
1161         if (co == NULL) return 0;
1162         // Do it
1163         lua_pushnumber(L, co->getRadYawDep());
1164         return 1;
1165 }
1166
1167 // get_look_pitch2(self)
1168 int ObjectRef::l_get_look_vertical(lua_State *L)
1169 {
1170         NO_MAP_LOCK_REQUIRED;
1171         ObjectRef *ref = checkobject(L, 1);
1172         PlayerSAO* co = getplayersao(ref);
1173         if (co == NULL) return 0;
1174         // Do it
1175         lua_pushnumber(L, co->getRadLookPitch());
1176         return 1;
1177 }
1178
1179 // get_look_yaw2(self)
1180 int ObjectRef::l_get_look_horizontal(lua_State *L)
1181 {
1182         NO_MAP_LOCK_REQUIRED;
1183         ObjectRef *ref = checkobject(L, 1);
1184         PlayerSAO* co = getplayersao(ref);
1185         if (co == NULL) return 0;
1186         // Do it
1187         lua_pushnumber(L, co->getRadRotation().Y);
1188         return 1;
1189 }
1190
1191 // set_look_vertical(self, radians)
1192 int ObjectRef::l_set_look_vertical(lua_State *L)
1193 {
1194         NO_MAP_LOCK_REQUIRED;
1195         ObjectRef *ref = checkobject(L, 1);
1196         PlayerSAO* co = getplayersao(ref);
1197         if (co == NULL) return 0;
1198         float pitch = readParam<float>(L, 2) * core::RADTODEG;
1199         // Do it
1200         co->setLookPitchAndSend(pitch);
1201         return 1;
1202 }
1203
1204 // set_look_horizontal(self, radians)
1205 int ObjectRef::l_set_look_horizontal(lua_State *L)
1206 {
1207         NO_MAP_LOCK_REQUIRED;
1208         ObjectRef *ref = checkobject(L, 1);
1209         PlayerSAO* co = getplayersao(ref);
1210         if (co == NULL) return 0;
1211         float yaw = readParam<float>(L, 2) * core::RADTODEG;
1212         // Do it
1213         co->setPlayerYawAndSend(yaw);
1214         return 1;
1215 }
1216
1217 // DEPRECATED
1218 // set_look_pitch(self, radians)
1219 int ObjectRef::l_set_look_pitch(lua_State *L)
1220 {
1221         NO_MAP_LOCK_REQUIRED;
1222
1223         log_deprecated(L,
1224                 "Deprecated call to set_look_pitch, use set_look_vertical instead.");
1225
1226         ObjectRef *ref = checkobject(L, 1);
1227         PlayerSAO* co = getplayersao(ref);
1228         if (co == NULL) return 0;
1229         float pitch = readParam<float>(L, 2) * core::RADTODEG;
1230         // Do it
1231         co->setLookPitchAndSend(pitch);
1232         return 1;
1233 }
1234
1235 // DEPRECATED
1236 // set_look_yaw(self, radians)
1237 int ObjectRef::l_set_look_yaw(lua_State *L)
1238 {
1239         NO_MAP_LOCK_REQUIRED;
1240
1241         log_deprecated(L,
1242                 "Deprecated call to set_look_yaw, use set_look_horizontal instead.");
1243
1244         ObjectRef *ref = checkobject(L, 1);
1245         PlayerSAO* co = getplayersao(ref);
1246         if (co == NULL) return 0;
1247         float yaw = readParam<float>(L, 2) * core::RADTODEG;
1248         // Do it
1249         co->setPlayerYawAndSend(yaw);
1250         return 1;
1251 }
1252
1253 // set_fov(self, degrees[, is_multiplier, transition_time])
1254 int ObjectRef::l_set_fov(lua_State *L)
1255 {
1256         NO_MAP_LOCK_REQUIRED;
1257         ObjectRef *ref = checkobject(L, 1);
1258         RemotePlayer *player = getplayer(ref);
1259         if (!player)
1260                 return 0;
1261
1262         player->setFov({
1263                 static_cast<f32>(luaL_checknumber(L, 2)),
1264                 readParam<bool>(L, 3, false),
1265                 lua_isnumber(L, 4) ? static_cast<f32>(luaL_checknumber(L, 4)) : 0.0f
1266         });
1267         getServer(L)->SendPlayerFov(player->getPeerId());
1268
1269         return 0;
1270 }
1271
1272 // get_fov(self)
1273 int ObjectRef::l_get_fov(lua_State *L)
1274 {
1275         NO_MAP_LOCK_REQUIRED;
1276         ObjectRef *ref = checkobject(L, 1);
1277         RemotePlayer *player = getplayer(ref);
1278         if (!player)
1279                 return 0;
1280
1281         PlayerFovSpec fov_spec = player->getFov();
1282         lua_pushnumber(L, fov_spec.fov);
1283         lua_pushboolean(L, fov_spec.is_multiplier);
1284         lua_pushnumber(L, fov_spec.transition_time);
1285
1286         return 3;
1287 }
1288
1289 // set_breath(self, breath)
1290 int ObjectRef::l_set_breath(lua_State *L)
1291 {
1292         NO_MAP_LOCK_REQUIRED;
1293         ObjectRef *ref = checkobject(L, 1);
1294         PlayerSAO* co = getplayersao(ref);
1295         if (co == NULL) return 0;
1296         u16 breath = luaL_checknumber(L, 2);
1297         co->setBreath(breath);
1298
1299         return 0;
1300 }
1301
1302 // get_breath(self)
1303 int ObjectRef::l_get_breath(lua_State *L)
1304 {
1305         NO_MAP_LOCK_REQUIRED;
1306         ObjectRef *ref = checkobject(L, 1);
1307         PlayerSAO* co = getplayersao(ref);
1308         if (co == NULL) return 0;
1309         // Do it
1310         u16 breath = co->getBreath();
1311         lua_pushinteger (L, breath);
1312         return 1;
1313 }
1314
1315 // set_attribute(self, attribute, value)
1316 int ObjectRef::l_set_attribute(lua_State *L)
1317 {
1318         log_deprecated(L,
1319                 "Deprecated call to set_attribute, use MetaDataRef methods instead.");
1320
1321         ObjectRef *ref = checkobject(L, 1);
1322         PlayerSAO* co = getplayersao(ref);
1323         if (co == NULL)
1324                 return 0;
1325
1326         std::string attr = luaL_checkstring(L, 2);
1327         if (lua_isnil(L, 3)) {
1328                 co->getMeta().removeString(attr);
1329         } else {
1330                 std::string value = luaL_checkstring(L, 3);
1331                 co->getMeta().setString(attr, value);
1332         }
1333         return 1;
1334 }
1335
1336 // get_attribute(self, attribute)
1337 int ObjectRef::l_get_attribute(lua_State *L)
1338 {
1339         log_deprecated(L,
1340                 "Deprecated call to get_attribute, use MetaDataRef methods instead.");
1341
1342         ObjectRef *ref = checkobject(L, 1);
1343         PlayerSAO* co = getplayersao(ref);
1344         if (co == NULL)
1345                 return 0;
1346
1347         std::string attr = luaL_checkstring(L, 2);
1348
1349         std::string value;
1350         if (co->getMeta().getStringToRef(attr, value)) {
1351                 lua_pushstring(L, value.c_str());
1352                 return 1;
1353         }
1354
1355         return 0;
1356 }
1357
1358
1359 // get_meta(self, attribute)
1360 int ObjectRef::l_get_meta(lua_State *L)
1361 {
1362         ObjectRef *ref = checkobject(L, 1);
1363         PlayerSAO *co = getplayersao(ref);
1364         if (co == NULL)
1365                 return 0;
1366
1367         PlayerMetaRef::create(L, &co->getMeta());
1368         return 1;
1369 }
1370
1371
1372 // set_inventory_formspec(self, formspec)
1373 int ObjectRef::l_set_inventory_formspec(lua_State *L)
1374 {
1375         NO_MAP_LOCK_REQUIRED;
1376         ObjectRef *ref = checkobject(L, 1);
1377         RemotePlayer *player = getplayer(ref);
1378         if (player == NULL) return 0;
1379         std::string formspec = luaL_checkstring(L, 2);
1380
1381         player->inventory_formspec = formspec;
1382         getServer(L)->reportInventoryFormspecModified(player->getName());
1383         lua_pushboolean(L, true);
1384         return 1;
1385 }
1386
1387 // get_inventory_formspec(self) -> formspec
1388 int ObjectRef::l_get_inventory_formspec(lua_State *L)
1389 {
1390         NO_MAP_LOCK_REQUIRED;
1391         ObjectRef *ref = checkobject(L, 1);
1392         RemotePlayer *player = getplayer(ref);
1393         if (player == NULL) return 0;
1394
1395         std::string formspec = player->inventory_formspec;
1396         lua_pushlstring(L, formspec.c_str(), formspec.size());
1397         return 1;
1398 }
1399
1400 // set_formspec_prepend(self, formspec)
1401 int ObjectRef::l_set_formspec_prepend(lua_State *L)
1402 {
1403         NO_MAP_LOCK_REQUIRED;
1404         ObjectRef *ref = checkobject(L, 1);
1405         RemotePlayer *player = getplayer(ref);
1406         if (player == NULL)
1407                 return 0;
1408
1409         std::string formspec = luaL_checkstring(L, 2);
1410
1411         player->formspec_prepend = formspec;
1412         getServer(L)->reportFormspecPrependModified(player->getName());
1413         lua_pushboolean(L, true);
1414         return 1;
1415 }
1416
1417 // get_formspec_prepend(self) -> formspec
1418 int ObjectRef::l_get_formspec_prepend(lua_State *L)
1419 {
1420         NO_MAP_LOCK_REQUIRED;
1421         ObjectRef *ref = checkobject(L, 1);
1422         RemotePlayer *player = getplayer(ref);
1423         if (player == NULL)
1424                  return 0;
1425
1426         std::string formspec = player->formspec_prepend;
1427         lua_pushlstring(L, formspec.c_str(), formspec.size());
1428         return 1;
1429 }
1430
1431 // get_player_control(self)
1432 int ObjectRef::l_get_player_control(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                 lua_pushlstring(L, "", 0);
1439                 return 1;
1440         }
1441
1442         const PlayerControl &control = player->getPlayerControl();
1443         lua_newtable(L);
1444         lua_pushboolean(L, control.up);
1445         lua_setfield(L, -2, "up");
1446         lua_pushboolean(L, control.down);
1447         lua_setfield(L, -2, "down");
1448         lua_pushboolean(L, control.left);
1449         lua_setfield(L, -2, "left");
1450         lua_pushboolean(L, control.right);
1451         lua_setfield(L, -2, "right");
1452         lua_pushboolean(L, control.jump);
1453         lua_setfield(L, -2, "jump");
1454         lua_pushboolean(L, control.aux1);
1455         lua_setfield(L, -2, "aux1");
1456         lua_pushboolean(L, control.sneak);
1457         lua_setfield(L, -2, "sneak");
1458         lua_pushboolean(L, control.dig);
1459         lua_setfield(L, -2, "dig");
1460         lua_pushboolean(L, control.place);
1461         lua_setfield(L, -2, "place");
1462         // Legacy fields to ensure mod compatibility
1463         lua_pushboolean(L, control.dig);
1464         lua_setfield(L, -2, "LMB");
1465         lua_pushboolean(L, control.place);
1466         lua_setfield(L, -2, "RMB");
1467         lua_pushboolean(L, control.zoom);
1468         lua_setfield(L, -2, "zoom");
1469         return 1;
1470 }
1471
1472 // get_player_control_bits(self)
1473 int ObjectRef::l_get_player_control_bits(lua_State *L)
1474 {
1475         NO_MAP_LOCK_REQUIRED;
1476         ObjectRef *ref = checkobject(L, 1);
1477         RemotePlayer *player = getplayer(ref);
1478         if (player == NULL) {
1479                 lua_pushlstring(L, "", 0);
1480                 return 1;
1481         }
1482         // Do it
1483         lua_pushnumber(L, player->keyPressed);
1484         return 1;
1485 }
1486
1487 // hud_add(self, form)
1488 int ObjectRef::l_hud_add(lua_State *L)
1489 {
1490         NO_MAP_LOCK_REQUIRED;
1491         ObjectRef *ref = checkobject(L, 1);
1492         RemotePlayer *player = getplayer(ref);
1493         if (player == NULL)
1494                 return 0;
1495
1496         HudElement *elem = new HudElement;
1497         read_hud_element(L, elem);
1498
1499         u32 id = getServer(L)->hudAdd(player, elem);
1500         if (id == U32_MAX) {
1501                 delete elem;
1502                 return 0;
1503         }
1504
1505         lua_pushnumber(L, id);
1506         return 1;
1507 }
1508
1509 // hud_remove(self, id)
1510 int ObjectRef::l_hud_remove(lua_State *L)
1511 {
1512         NO_MAP_LOCK_REQUIRED;
1513         ObjectRef *ref = checkobject(L, 1);
1514         RemotePlayer *player = getplayer(ref);
1515         if (player == NULL)
1516                 return 0;
1517
1518         u32 id = -1;
1519         if (!lua_isnil(L, 2))
1520                 id = lua_tonumber(L, 2);
1521
1522         if (!getServer(L)->hudRemove(player, id))
1523                 return 0;
1524
1525         lua_pushboolean(L, true);
1526         return 1;
1527 }
1528
1529 // hud_change(self, id, stat, data)
1530 int ObjectRef::l_hud_change(lua_State *L)
1531 {
1532         NO_MAP_LOCK_REQUIRED;
1533         ObjectRef *ref = checkobject(L, 1);
1534         RemotePlayer *player = getplayer(ref);
1535         if (player == NULL)
1536                 return 0;
1537
1538         u32 id = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : -1;
1539
1540         HudElement *e = player->getHud(id);
1541         if (!e)
1542                 return 0;
1543
1544         void *value = NULL;
1545         HudElementStat stat = read_hud_change(L, e, &value);
1546
1547         getServer(L)->hudChange(player, id, stat, value);
1548
1549         lua_pushboolean(L, true);
1550         return 1;
1551 }
1552
1553 // hud_get(self, id)
1554 int ObjectRef::l_hud_get(lua_State *L)
1555 {
1556         NO_MAP_LOCK_REQUIRED;
1557         ObjectRef *ref = checkobject(L, 1);
1558         RemotePlayer *player = getplayer(ref);
1559         if (player == NULL)
1560                 return 0;
1561
1562         u32 id = lua_tonumber(L, -1);
1563
1564         HudElement *e = player->getHud(id);
1565         if (!e)
1566                 return 0;
1567         push_hud_element(L, e);
1568         return 1;
1569 }
1570
1571 // hud_set_flags(self, flags)
1572 int ObjectRef::l_hud_set_flags(lua_State *L)
1573 {
1574         NO_MAP_LOCK_REQUIRED;
1575         ObjectRef *ref = checkobject(L, 1);
1576         RemotePlayer *player = getplayer(ref);
1577         if (player == NULL)
1578                 return 0;
1579
1580         u32 flags = 0;
1581         u32 mask  = 0;
1582         bool flag;
1583
1584         const EnumString *esp = es_HudBuiltinElement;
1585         for (int i = 0; esp[i].str; i++) {
1586                 if (getboolfield(L, 2, esp[i].str, flag)) {
1587                         flags |= esp[i].num * flag;
1588                         mask  |= esp[i].num;
1589                 }
1590         }
1591         if (!getServer(L)->hudSetFlags(player, flags, mask))
1592                 return 0;
1593
1594         lua_pushboolean(L, true);
1595         return 1;
1596 }
1597
1598 int ObjectRef::l_hud_get_flags(lua_State *L)
1599 {
1600         NO_MAP_LOCK_REQUIRED;
1601         ObjectRef *ref = checkobject(L, 1);
1602         RemotePlayer *player = getplayer(ref);
1603         if (player == NULL)
1604                 return 0;
1605
1606         lua_newtable(L);
1607         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE);
1608         lua_setfield(L, -2, "hotbar");
1609         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE);
1610         lua_setfield(L, -2, "healthbar");
1611         lua_pushboolean(L, player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE);
1612         lua_setfield(L, -2, "crosshair");
1613         lua_pushboolean(L, player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE);
1614         lua_setfield(L, -2, "wielditem");
1615         lua_pushboolean(L, player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE);
1616         lua_setfield(L, -2, "breathbar");
1617         lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
1618         lua_setfield(L, -2, "minimap");
1619         lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE);
1620         lua_setfield(L, -2, "minimap_radar");
1621
1622         return 1;
1623 }
1624
1625 // hud_set_hotbar_itemcount(self, hotbar_itemcount)
1626 int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
1627 {
1628         NO_MAP_LOCK_REQUIRED;
1629         ObjectRef *ref = checkobject(L, 1);
1630         RemotePlayer *player = getplayer(ref);
1631         if (player == NULL)
1632                 return 0;
1633
1634         s32 hotbar_itemcount = lua_tonumber(L, 2);
1635
1636         if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
1637                 return 0;
1638
1639         lua_pushboolean(L, true);
1640         return 1;
1641 }
1642
1643 // hud_get_hotbar_itemcount(self)
1644 int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
1645 {
1646         NO_MAP_LOCK_REQUIRED;
1647         ObjectRef *ref = checkobject(L, 1);
1648         RemotePlayer *player = getplayer(ref);
1649         if (player == NULL)
1650                 return 0;
1651
1652         lua_pushnumber(L, player->getHotbarItemcount());
1653         return 1;
1654 }
1655
1656 // hud_set_hotbar_image(self, name)
1657 int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
1658 {
1659         NO_MAP_LOCK_REQUIRED;
1660         ObjectRef *ref = checkobject(L, 1);
1661         RemotePlayer *player = getplayer(ref);
1662         if (player == NULL)
1663                 return 0;
1664
1665         std::string name = readParam<std::string>(L, 2);
1666
1667         getServer(L)->hudSetHotbarImage(player, name);
1668         return 1;
1669 }
1670
1671 // hud_get_hotbar_image(self)
1672 int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
1673 {
1674         NO_MAP_LOCK_REQUIRED;
1675         ObjectRef *ref = checkobject(L, 1);
1676         RemotePlayer *player = getplayer(ref);
1677         if (player == NULL)
1678                 return 0;
1679
1680         const std::string &name = player->getHotbarImage();
1681         lua_pushlstring(L, name.c_str(), name.size());
1682         return 1;
1683 }
1684
1685 // hud_set_hotbar_selected_image(self, name)
1686 int ObjectRef::l_hud_set_hotbar_selected_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         std::string name = readParam<std::string>(L, 2);
1695
1696         getServer(L)->hudSetHotbarSelectedImage(player, name);
1697         return 1;
1698 }
1699
1700 // hud_get_hotbar_selected_image(self)
1701 int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
1702 {
1703         NO_MAP_LOCK_REQUIRED;
1704         ObjectRef *ref = checkobject(L, 1);
1705         RemotePlayer *player = getplayer(ref);
1706         if (player == NULL)
1707                 return 0;
1708
1709         const std::string &name = player->getHotbarSelectedImage();
1710         lua_pushlstring(L, name.c_str(), name.size());
1711         return 1;
1712 }
1713
1714 // set_sky(self, {base_color=, type=, textures=, clouds=, sky_colors={}})
1715 int ObjectRef::l_set_sky(lua_State *L)
1716 {
1717         NO_MAP_LOCK_REQUIRED;
1718         ObjectRef *ref = checkobject(L, 1);
1719         RemotePlayer *player = getplayer(ref);
1720         if (!player)
1721                 return 0;
1722
1723         bool is_colorspec = is_color_table(L, 2);
1724
1725         SkyboxParams skybox_params = player->getSkyParams();
1726         if (lua_istable(L, 2) && !is_colorspec) {
1727                 lua_getfield(L, 2, "base_color");
1728                 if (!lua_isnil(L, -1))
1729                         read_color(L, -1, &skybox_params.bgcolor);
1730                 lua_pop(L, 1);
1731
1732                 lua_getfield(L, 2, "type");
1733                 if (!lua_isnil(L, -1))
1734                         skybox_params.type = luaL_checkstring(L, -1);
1735                 lua_pop(L, 1);
1736
1737                 lua_getfield(L, 2, "textures");
1738                 skybox_params.textures.clear();
1739                 if (lua_istable(L, -1) && skybox_params.type == "skybox") {
1740                         lua_pushnil(L);
1741                         while (lua_next(L, -2) != 0) {
1742                                 // Key is at index -2 and value at index -1
1743                                 skybox_params.textures.emplace_back(readParam<std::string>(L, -1));
1744                                 // Removes the value, but keeps the key for iteration
1745                                 lua_pop(L, 1);
1746                         }
1747                 }
1748                 lua_pop(L, 1);
1749
1750                 /*
1751                 We want to avoid crashes, so we're checking even if we're not using them.
1752                 However, we want to ensure that the skybox can be set to nil when
1753                 using "regular" or "plain" skybox modes as textures aren't needed.
1754                 */
1755
1756                 if (skybox_params.textures.size() != 6 && skybox_params.textures.size() > 0)
1757                         throw LuaError("Skybox expects 6 textures!");
1758
1759                 skybox_params.clouds = getboolfield_default(L, 2,
1760                         "clouds", skybox_params.clouds);
1761
1762                 lua_getfield(L, 2, "sky_color");
1763                 if (lua_istable(L, -1)) {
1764                         lua_getfield(L, -1, "day_sky");
1765                         read_color(L, -1, &skybox_params.sky_color.day_sky);
1766                         lua_pop(L, 1);
1767
1768                         lua_getfield(L, -1, "day_horizon");
1769                         read_color(L, -1, &skybox_params.sky_color.day_horizon);
1770                         lua_pop(L, 1);
1771
1772                         lua_getfield(L, -1, "dawn_sky");
1773                         read_color(L, -1, &skybox_params.sky_color.dawn_sky);
1774                         lua_pop(L, 1);
1775
1776                         lua_getfield(L, -1, "dawn_horizon");
1777                         read_color(L, -1, &skybox_params.sky_color.dawn_horizon);
1778                         lua_pop(L, 1);
1779
1780                         lua_getfield(L, -1, "night_sky");
1781                         read_color(L, -1, &skybox_params.sky_color.night_sky);
1782                         lua_pop(L, 1);
1783
1784                         lua_getfield(L, -1, "night_horizon");
1785                         read_color(L, -1, &skybox_params.sky_color.night_horizon);
1786                         lua_pop(L, 1);
1787
1788                         lua_getfield(L, -1, "indoors");
1789                         read_color(L, -1, &skybox_params.sky_color.indoors);
1790                         lua_pop(L, 1);
1791
1792                         // Prevent flickering clouds at dawn/dusk:
1793                         skybox_params.fog_sun_tint = video::SColor(255, 255, 255, 255);
1794                         lua_getfield(L, -1, "fog_sun_tint");
1795                         read_color(L, -1, &skybox_params.fog_sun_tint);
1796                         lua_pop(L, 1);
1797
1798                         skybox_params.fog_moon_tint = video::SColor(255, 255, 255, 255);
1799                         lua_getfield(L, -1, "fog_moon_tint");
1800                         read_color(L, -1, &skybox_params.fog_moon_tint);
1801                         lua_pop(L, 1);
1802
1803                         lua_getfield(L, -1, "fog_tint_type");
1804                         if (!lua_isnil(L, -1))
1805                                 skybox_params.fog_tint_type = luaL_checkstring(L, -1);
1806                         lua_pop(L, 1);
1807
1808                         // Because we need to leave the "sky_color" table.
1809                         lua_pop(L, 1);
1810                 }
1811         } else {
1812                 // Handle old set_sky calls, and log deprecated:
1813                 log_deprecated(L, "Deprecated call to set_sky, please check lua_api.txt");
1814
1815                 // Fix sun, moon and stars showing when classic textured skyboxes are used
1816                 SunParams sun_params = player->getSunParams();
1817                 MoonParams moon_params = player->getMoonParams();
1818                 StarParams star_params = player->getStarParams();
1819
1820                 // Prevent erroneous background colors
1821                 skybox_params.bgcolor = video::SColor(255, 255, 255, 255);
1822                 read_color(L, 2, &skybox_params.bgcolor);
1823
1824                 skybox_params.type = luaL_checkstring(L, 3);
1825
1826                 // Preserve old behaviour of the sun, moon and stars
1827                 // when using the old set_sky call.
1828                 if (skybox_params.type == "regular") {
1829                         sun_params.visible = true;
1830                         sun_params.sunrise_visible = true;
1831                         moon_params.visible = true;
1832                         star_params.visible = true;
1833                 } else {
1834                         sun_params.visible = false;
1835                         sun_params.sunrise_visible = false;
1836                         moon_params.visible = false;
1837                         star_params.visible = false;
1838                 }
1839
1840                 skybox_params.textures.clear();
1841                 if (lua_istable(L, 4)) {
1842                         lua_pushnil(L);
1843                         while (lua_next(L, 4) != 0) {
1844                         // Key at index -2, and value at index -1
1845                                 if (lua_isstring(L, -1))
1846                                         skybox_params.textures.emplace_back(readParam<std::string>(L, -1));
1847                                 else
1848                                         skybox_params.textures.emplace_back("");
1849                                 // Remove the value, keep the key for the next iteration
1850                                 lua_pop(L, 1);
1851                         }
1852                 }
1853                 if (skybox_params.type == "skybox" && skybox_params.textures.size() != 6)
1854                         throw LuaError("Skybox expects 6 textures.");
1855
1856                 skybox_params.clouds = true;
1857                 if (lua_isboolean(L, 5))
1858                         skybox_params.clouds = readParam<bool>(L, 5);
1859
1860                 getServer(L)->setSun(player, sun_params);
1861                 getServer(L)->setMoon(player, moon_params);
1862                 getServer(L)->setStars(player, star_params);
1863         }
1864         getServer(L)->setSky(player, skybox_params);
1865         lua_pushboolean(L, true);
1866         return 1;
1867 }
1868
1869 // get_sky(self)
1870 int ObjectRef::l_get_sky(lua_State *L)
1871 {
1872         NO_MAP_LOCK_REQUIRED;
1873         ObjectRef *ref = checkobject(L, 1);
1874         RemotePlayer *player = getplayer(ref);
1875
1876         if (!player)
1877                 return 0;
1878         SkyboxParams skybox_params;
1879         skybox_params = player->getSkyParams();
1880
1881         push_ARGB8(L, skybox_params.bgcolor);
1882         lua_pushlstring(L, skybox_params.type.c_str(), skybox_params.type.size());
1883
1884         lua_newtable(L);
1885         s16 i = 1;
1886         for (const std::string& texture : skybox_params.textures) {
1887                 lua_pushlstring(L, texture.c_str(), texture.size());
1888                 lua_rawseti(L, -2, i++);
1889         }
1890         lua_pushboolean(L, skybox_params.clouds);
1891         return 4;
1892 }
1893
1894 // get_sky_color(self)
1895 int ObjectRef::l_get_sky_color(lua_State *L)
1896 {
1897         NO_MAP_LOCK_REQUIRED;
1898         ObjectRef *ref = checkobject(L, 1);
1899         RemotePlayer *player = getplayer(ref);
1900
1901         if (!player)
1902                 return 0;
1903
1904         const SkyboxParams& skybox_params = player->getSkyParams();
1905
1906         lua_newtable(L);
1907         if (skybox_params.type == "regular") {
1908                 push_ARGB8(L, skybox_params.sky_color.day_sky);
1909                 lua_setfield(L, -2, "day_sky");
1910                 push_ARGB8(L, skybox_params.sky_color.day_horizon);
1911                 lua_setfield(L, -2, "day_horizon");
1912                 push_ARGB8(L, skybox_params.sky_color.dawn_sky);
1913                 lua_setfield(L, -2, "dawn_sky");
1914                 push_ARGB8(L, skybox_params.sky_color.dawn_horizon);
1915                 lua_setfield(L, -2, "dawn_horizon");
1916                 push_ARGB8(L, skybox_params.sky_color.night_sky);
1917                 lua_setfield(L, -2, "night_sky");
1918                 push_ARGB8(L, skybox_params.sky_color.night_horizon);
1919                 lua_setfield(L, -2, "night_horizon");
1920                 push_ARGB8(L, skybox_params.sky_color.indoors);
1921                 lua_setfield(L, -2, "indoors");
1922         }
1923         push_ARGB8(L, skybox_params.fog_sun_tint);
1924         lua_setfield(L, -2, "fog_sun_tint");
1925         push_ARGB8(L, skybox_params.fog_moon_tint);
1926         lua_setfield(L, -2, "fog_moon_tint");
1927         lua_pushstring(L, skybox_params.fog_tint_type.c_str());
1928         lua_setfield(L, -2, "fog_tint_type");
1929         return 1;
1930 }
1931
1932 // set_sun(self, {visible, texture=, tonemap=, sunrise=, rotation=, scale=})
1933 int ObjectRef::l_set_sun(lua_State *L)
1934 {
1935         NO_MAP_LOCK_REQUIRED;
1936         ObjectRef *ref = checkobject(L, 1);
1937         RemotePlayer *player = getplayer(ref);
1938         if (!player)
1939                 return 0;
1940
1941         if (!lua_istable(L, 2))
1942                 return 0;
1943
1944         SunParams sun_params = player->getSunParams();
1945
1946         sun_params.visible = getboolfield_default(L, 2,
1947                         "visible", sun_params.visible);
1948         sun_params.texture = getstringfield_default(L, 2,
1949                         "texture", sun_params.texture);
1950         sun_params.tonemap = getstringfield_default(L, 2,
1951                         "tonemap", sun_params.tonemap);
1952         sun_params.sunrise = getstringfield_default(L, 2,
1953                         "sunrise", sun_params.sunrise);
1954         sun_params.sunrise_visible = getboolfield_default(L, 2,
1955                         "sunrise_visible", sun_params.sunrise_visible);
1956         sun_params.scale = getfloatfield_default(L, 2,
1957                         "scale", sun_params.scale);
1958
1959         getServer(L)->setSun(player, sun_params);
1960         lua_pushboolean(L, true);
1961         return 1;
1962 }
1963
1964 //get_sun(self)
1965 int ObjectRef::l_get_sun(lua_State *L)
1966 {
1967         NO_MAP_LOCK_REQUIRED;
1968         ObjectRef *ref = checkobject(L, 1);
1969         RemotePlayer *player = getplayer(ref);
1970         if (!player)
1971                 return 0;
1972         const SunParams &sun_params = player->getSunParams();
1973
1974         lua_newtable(L);
1975         lua_pushboolean(L, sun_params.visible);
1976         lua_setfield(L, -2, "visible");
1977         lua_pushstring(L, sun_params.texture.c_str());
1978         lua_setfield(L, -2, "texture");
1979         lua_pushstring(L, sun_params.tonemap.c_str());
1980         lua_setfield(L, -2, "tonemap");
1981         lua_pushstring(L, sun_params.sunrise.c_str());
1982         lua_setfield(L, -2, "sunrise");
1983         lua_pushboolean(L, sun_params.sunrise_visible);
1984         lua_setfield(L, -2, "sunrise_visible");
1985         lua_pushnumber(L, sun_params.scale);
1986         lua_setfield(L, -2, "scale");
1987
1988         return 1;
1989 }
1990
1991 // set_moon(self, {visible, texture=, tonemap=, sunrise=, rotation=, scale=})
1992 int ObjectRef::l_set_moon(lua_State *L)
1993 {
1994         NO_MAP_LOCK_REQUIRED;
1995         ObjectRef *ref = checkobject(L, 1);
1996         RemotePlayer *player = getplayer(ref);
1997         if (!player)
1998                 return 0;
1999         if (!lua_istable(L, 2))
2000                 return 0;
2001
2002         MoonParams moon_params = player->getMoonParams();
2003
2004         moon_params.visible = getboolfield_default(L, 2,
2005                 "visible", moon_params.visible);
2006         moon_params.texture = getstringfield_default(L, 2,
2007                 "texture", moon_params.texture);
2008         moon_params.tonemap = getstringfield_default(L, 2,
2009                 "tonemap", moon_params.tonemap);
2010         moon_params.scale = getfloatfield_default(L, 2,
2011                 "scale", moon_params.scale);
2012
2013         getServer(L)->setMoon(player, moon_params);
2014         lua_pushboolean(L, true);
2015         return 1;
2016 }
2017
2018 // get_moon(self)
2019 int ObjectRef::l_get_moon(lua_State *L)
2020 {
2021         NO_MAP_LOCK_REQUIRED;
2022         ObjectRef *ref = checkobject(L, 1);
2023         RemotePlayer *player = getplayer(ref);
2024         if (!player)
2025                 return 0;
2026         const MoonParams &moon_params = player->getMoonParams();
2027
2028         lua_newtable(L);
2029         lua_pushboolean(L, moon_params.visible);
2030         lua_setfield(L, -2, "visible");
2031         lua_pushstring(L, moon_params.texture.c_str());
2032         lua_setfield(L, -2, "texture");
2033         lua_pushstring(L, moon_params.tonemap.c_str());
2034         lua_setfield(L, -2, "tonemap");
2035         lua_pushnumber(L, moon_params.scale);
2036         lua_setfield(L, -2, "scale");
2037
2038         return 1;
2039 }
2040
2041 // set_stars(self, {visible, count=, starcolor=, rotation=, scale=})
2042 int ObjectRef::l_set_stars(lua_State *L)
2043 {
2044         NO_MAP_LOCK_REQUIRED;
2045         ObjectRef *ref = checkobject(L, 1);
2046         RemotePlayer *player = getplayer(ref);
2047         if (!player)
2048                 return 0;
2049         if (!lua_istable(L, 2))
2050                 return 0;
2051
2052         StarParams star_params = player->getStarParams();
2053
2054         star_params.visible = getboolfield_default(L, 2,
2055                 "visible", star_params.visible);
2056         star_params.count = getintfield_default(L, 2,
2057                 "count", star_params.count);
2058
2059         lua_getfield(L, 2, "star_color");
2060         if (!lua_isnil(L, -1))
2061                 read_color(L, -1, &star_params.starcolor);
2062         lua_pop(L, 1);
2063
2064         star_params.scale = getfloatfield_default(L, 2,
2065                 "scale", star_params.scale);
2066
2067         getServer(L)->setStars(player, star_params);
2068         lua_pushboolean(L, true);
2069         return 1;
2070 }
2071
2072 // get_stars(self)
2073 int ObjectRef::l_get_stars(lua_State *L)
2074 {
2075         NO_MAP_LOCK_REQUIRED;
2076         ObjectRef *ref = checkobject(L, 1);
2077         RemotePlayer *player = getplayer(ref);
2078         if (!player)
2079                 return 0;
2080         const StarParams &star_params = player->getStarParams();
2081
2082         lua_newtable(L);
2083         lua_pushboolean(L, star_params.visible);
2084         lua_setfield(L, -2, "visible");
2085         lua_pushnumber(L, star_params.count);
2086         lua_setfield(L, -2, "count");
2087         push_ARGB8(L, star_params.starcolor);
2088         lua_setfield(L, -2, "star_color");
2089         lua_pushnumber(L, star_params.scale);
2090         lua_setfield(L, -2, "scale");
2091
2092         return 1;
2093 }
2094
2095 // set_clouds(self, {density=, color=, ambient=, height=, thickness=, speed=})
2096 int ObjectRef::l_set_clouds(lua_State *L)
2097 {
2098         NO_MAP_LOCK_REQUIRED;
2099         ObjectRef *ref = checkobject(L, 1);
2100         RemotePlayer *player = getplayer(ref);
2101         if (!player)
2102                 return 0;
2103         if (!lua_istable(L, 2))
2104                 return 0;
2105
2106         CloudParams cloud_params = player->getCloudParams();
2107
2108         cloud_params.density = getfloatfield_default(L, 2, "density", cloud_params.density);
2109
2110         lua_getfield(L, 2, "color");
2111         if (!lua_isnil(L, -1))
2112                 read_color(L, -1, &cloud_params.color_bright);
2113         lua_pop(L, 1);
2114         lua_getfield(L, 2, "ambient");
2115         if (!lua_isnil(L, -1))
2116                 read_color(L, -1, &cloud_params.color_ambient);
2117         lua_pop(L, 1);
2118
2119         cloud_params.height    = getfloatfield_default(L, 2, "height",    cloud_params.height   );
2120         cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness);
2121
2122         lua_getfield(L, 2, "speed");
2123         if (lua_istable(L, -1)) {
2124                 v2f new_speed;
2125                 new_speed.X = getfloatfield_default(L, -1, "x", 0);
2126                 new_speed.Y = getfloatfield_default(L, -1, "z", 0);
2127                 cloud_params.speed = new_speed;
2128         }
2129         lua_pop(L, 1);
2130
2131         getServer(L)->setClouds(player, cloud_params);
2132         lua_pushboolean(L, true);
2133         return 1;
2134 }
2135
2136 int ObjectRef::l_get_clouds(lua_State *L)
2137 {
2138         NO_MAP_LOCK_REQUIRED;
2139         ObjectRef *ref = checkobject(L, 1);
2140         RemotePlayer *player = getplayer(ref);
2141         if (!player)
2142                 return 0;
2143         const CloudParams &cloud_params = player->getCloudParams();
2144
2145         lua_newtable(L);
2146         lua_pushnumber(L, cloud_params.density);
2147         lua_setfield(L, -2, "density");
2148         push_ARGB8(L, cloud_params.color_bright);
2149         lua_setfield(L, -2, "color");
2150         push_ARGB8(L, cloud_params.color_ambient);
2151         lua_setfield(L, -2, "ambient");
2152         lua_pushnumber(L, cloud_params.height);
2153         lua_setfield(L, -2, "height");
2154         lua_pushnumber(L, cloud_params.thickness);
2155         lua_setfield(L, -2, "thickness");
2156         lua_newtable(L);
2157         lua_pushnumber(L, cloud_params.speed.X);
2158         lua_setfield(L, -2, "x");
2159         lua_pushnumber(L, cloud_params.speed.Y);
2160         lua_setfield(L, -2, "y");
2161         lua_setfield(L, -2, "speed");
2162
2163         return 1;
2164 }
2165
2166
2167 // override_day_night_ratio(self, brightness=0...1)
2168 int ObjectRef::l_override_day_night_ratio(lua_State *L)
2169 {
2170         NO_MAP_LOCK_REQUIRED;
2171         ObjectRef *ref = checkobject(L, 1);
2172         RemotePlayer *player = getplayer(ref);
2173         if (player == NULL)
2174                 return 0;
2175
2176         bool do_override = false;
2177         float ratio = 0.0f;
2178         if (!lua_isnil(L, 2)) {
2179                 do_override = true;
2180                 ratio = readParam<float>(L, 2);
2181         }
2182
2183         getServer(L)->overrideDayNightRatio(player, do_override, ratio);
2184         lua_pushboolean(L, true);
2185         return 1;
2186 }
2187
2188 // get_day_night_ratio(self)
2189 int ObjectRef::l_get_day_night_ratio(lua_State *L)
2190 {
2191         NO_MAP_LOCK_REQUIRED;
2192         ObjectRef *ref = checkobject(L, 1);
2193         RemotePlayer *player = getplayer(ref);
2194         if (player == NULL)
2195                 return 0;
2196
2197         bool do_override;
2198         float ratio;
2199         player->getDayNightRatio(&do_override, &ratio);
2200
2201         if (do_override)
2202                 lua_pushnumber(L, ratio);
2203         else
2204                 lua_pushnil(L);
2205
2206         return 1;
2207 }
2208
2209 ObjectRef::ObjectRef(ServerActiveObject *object):
2210         m_object(object)
2211 {
2212         //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
2213 }
2214
2215 // Creates an ObjectRef and leaves it on top of stack
2216 // Not callable from Lua; all references are created on the C side.
2217 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
2218 {
2219         ObjectRef *o = new ObjectRef(object);
2220         //infostream<<"ObjectRef::create: o="<<o<<std::endl;
2221         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2222         luaL_getmetatable(L, className);
2223         lua_setmetatable(L, -2);
2224 }
2225
2226 void ObjectRef::set_null(lua_State *L)
2227 {
2228         ObjectRef *o = checkobject(L, -1);
2229         o->m_object = NULL;
2230 }
2231
2232 void ObjectRef::Register(lua_State *L)
2233 {
2234         lua_newtable(L);
2235         int methodtable = lua_gettop(L);
2236         luaL_newmetatable(L, className);
2237         int metatable = lua_gettop(L);
2238
2239         lua_pushliteral(L, "__metatable");
2240         lua_pushvalue(L, methodtable);
2241         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
2242
2243         lua_pushliteral(L, "__index");
2244         lua_pushvalue(L, methodtable);
2245         lua_settable(L, metatable);
2246
2247         lua_pushliteral(L, "__gc");
2248         lua_pushcfunction(L, gc_object);
2249         lua_settable(L, metatable);
2250
2251         lua_pop(L, 1);  // drop metatable
2252
2253         markAliasDeprecated(methods);
2254         luaL_openlib(L, 0, methods, 0);  // fill methodtable
2255         lua_pop(L, 1);  // drop methodtable
2256
2257         // Cannot be created from Lua
2258         //lua_register(L, className, create_object);
2259 }
2260
2261 const char ObjectRef::className[] = "ObjectRef";
2262 luaL_Reg ObjectRef::methods[] = {
2263         // ServerActiveObject
2264         luamethod(ObjectRef, remove),
2265         luamethod_aliased(ObjectRef, get_pos, getpos),
2266         luamethod_aliased(ObjectRef, set_pos, setpos),
2267         luamethod_aliased(ObjectRef, move_to, moveto),
2268         luamethod(ObjectRef, punch),
2269         luamethod(ObjectRef, right_click),
2270         luamethod(ObjectRef, set_hp),
2271         luamethod(ObjectRef, get_hp),
2272         luamethod(ObjectRef, get_inventory),
2273         luamethod(ObjectRef, get_wield_list),
2274         luamethod(ObjectRef, get_wield_index),
2275         luamethod(ObjectRef, get_wielded_item),
2276         luamethod(ObjectRef, set_wielded_item),
2277         luamethod(ObjectRef, set_armor_groups),
2278         luamethod(ObjectRef, get_armor_groups),
2279         luamethod(ObjectRef, set_animation),
2280         luamethod(ObjectRef, get_animation),
2281         luamethod(ObjectRef, set_animation_frame_speed),
2282         luamethod(ObjectRef, set_bone_position),
2283         luamethod(ObjectRef, get_bone_position),
2284         luamethod(ObjectRef, set_attach),
2285         luamethod(ObjectRef, get_attach),
2286         luamethod(ObjectRef, set_detach),
2287         luamethod(ObjectRef, set_properties),
2288         luamethod(ObjectRef, get_properties),
2289         luamethod(ObjectRef, set_nametag_attributes),
2290         luamethod(ObjectRef, get_nametag_attributes),
2291         // LuaEntitySAO-only
2292         luamethod_aliased(ObjectRef, set_velocity, setvelocity),
2293         luamethod(ObjectRef, add_velocity),
2294         luamethod_aliased(ObjectRef, get_velocity, getvelocity),
2295         luamethod_aliased(ObjectRef, set_acceleration, setacceleration),
2296         luamethod_aliased(ObjectRef, get_acceleration, getacceleration),
2297         luamethod_aliased(ObjectRef, set_yaw, setyaw),
2298         luamethod_aliased(ObjectRef, get_yaw, getyaw),
2299         luamethod(ObjectRef, set_rotation),
2300         luamethod(ObjectRef, get_rotation),
2301         luamethod_aliased(ObjectRef, set_texture_mod, settexturemod),
2302         luamethod(ObjectRef, get_texture_mod),
2303         luamethod_aliased(ObjectRef, set_sprite, setsprite),
2304         luamethod(ObjectRef, get_entity_name),
2305         luamethod(ObjectRef, get_luaentity),
2306         // Player-only
2307         luamethod(ObjectRef, is_player),
2308         luamethod(ObjectRef, is_player_connected),
2309         luamethod(ObjectRef, get_player_name),
2310         luamethod(ObjectRef, get_player_velocity),
2311         luamethod(ObjectRef, add_player_velocity),
2312         luamethod(ObjectRef, get_look_dir),
2313         luamethod(ObjectRef, get_look_pitch),
2314         luamethod(ObjectRef, get_look_yaw),
2315         luamethod(ObjectRef, get_look_vertical),
2316         luamethod(ObjectRef, get_look_horizontal),
2317         luamethod(ObjectRef, set_look_horizontal),
2318         luamethod(ObjectRef, set_look_vertical),
2319         luamethod(ObjectRef, set_look_yaw),
2320         luamethod(ObjectRef, set_look_pitch),
2321         luamethod(ObjectRef, get_fov),
2322         luamethod(ObjectRef, set_fov),
2323         luamethod(ObjectRef, get_breath),
2324         luamethod(ObjectRef, set_breath),
2325         luamethod(ObjectRef, get_attribute),
2326         luamethod(ObjectRef, set_attribute),
2327         luamethod(ObjectRef, get_meta),
2328         luamethod(ObjectRef, set_inventory_formspec),
2329         luamethod(ObjectRef, get_inventory_formspec),
2330         luamethod(ObjectRef, set_formspec_prepend),
2331         luamethod(ObjectRef, get_formspec_prepend),
2332         luamethod(ObjectRef, get_player_control),
2333         luamethod(ObjectRef, get_player_control_bits),
2334         luamethod(ObjectRef, set_physics_override),
2335         luamethod(ObjectRef, get_physics_override),
2336         luamethod(ObjectRef, hud_add),
2337         luamethod(ObjectRef, hud_remove),
2338         luamethod(ObjectRef, hud_change),
2339         luamethod(ObjectRef, hud_get),
2340         luamethod(ObjectRef, hud_set_flags),
2341         luamethod(ObjectRef, hud_get_flags),
2342         luamethod(ObjectRef, hud_set_hotbar_itemcount),
2343         luamethod(ObjectRef, hud_get_hotbar_itemcount),
2344         luamethod(ObjectRef, hud_set_hotbar_image),
2345         luamethod(ObjectRef, hud_get_hotbar_image),
2346         luamethod(ObjectRef, hud_set_hotbar_selected_image),
2347         luamethod(ObjectRef, hud_get_hotbar_selected_image),
2348         luamethod(ObjectRef, set_sky),
2349         luamethod(ObjectRef, get_sky),
2350         luamethod(ObjectRef, get_sky_color),
2351         luamethod(ObjectRef, set_sun),
2352         luamethod(ObjectRef, get_sun),
2353         luamethod(ObjectRef, set_moon),
2354         luamethod(ObjectRef, get_moon),
2355         luamethod(ObjectRef, set_stars),
2356         luamethod(ObjectRef, get_stars),
2357         luamethod(ObjectRef, set_clouds),
2358         luamethod(ObjectRef, get_clouds),
2359         luamethod(ObjectRef, override_day_night_ratio),
2360         luamethod(ObjectRef, get_day_night_ratio),
2361         luamethod(ObjectRef, set_local_animation),
2362         luamethod(ObjectRef, get_local_animation),
2363         luamethod(ObjectRef, set_eye_offset),
2364         luamethod(ObjectRef, get_eye_offset),
2365         luamethod(ObjectRef, send_mapblock),
2366         {0,0}
2367 };