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