0a9f3117b3d7a41df71535b3b637d82f6bd66a75
[oweals/minetest.git] / src / script / lua_api / l_object.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "lua_api/l_object.h"
21 #include <cmath>
22 #include "lua_api/l_internal.h"
23 #include "lua_api/l_inventory.h"
24 #include "lua_api/l_item.h"
25 #include "lua_api/l_playermeta.h"
26 #include "common/c_converter.h"
27 #include "common/c_content.h"
28 #include "log.h"
29 #include "tool.h"
30 #include "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.LMB);
1459         lua_setfield(L, -2, "LMB");
1460         lua_pushboolean(L, control.RMB);
1461         lua_setfield(L, -2, "RMB");
1462         return 1;
1463 }
1464
1465 // get_player_control_bits(self)
1466 int ObjectRef::l_get_player_control_bits(lua_State *L)
1467 {
1468         NO_MAP_LOCK_REQUIRED;
1469         ObjectRef *ref = checkobject(L, 1);
1470         RemotePlayer *player = getplayer(ref);
1471         if (player == NULL) {
1472                 lua_pushlstring(L, "", 0);
1473                 return 1;
1474         }
1475         // Do it
1476         lua_pushnumber(L, player->keyPressed);
1477         return 1;
1478 }
1479
1480 // hud_add(self, form)
1481 int ObjectRef::l_hud_add(lua_State *L)
1482 {
1483         NO_MAP_LOCK_REQUIRED;
1484         ObjectRef *ref = checkobject(L, 1);
1485         RemotePlayer *player = getplayer(ref);
1486         if (player == NULL)
1487                 return 0;
1488
1489         HudElement *elem = new HudElement;
1490         read_hud_element(L, elem);
1491
1492         u32 id = getServer(L)->hudAdd(player, elem);
1493         if (id == U32_MAX) {
1494                 delete elem;
1495                 return 0;
1496         }
1497
1498         lua_pushnumber(L, id);
1499         return 1;
1500 }
1501
1502 // hud_remove(self, id)
1503 int ObjectRef::l_hud_remove(lua_State *L)
1504 {
1505         NO_MAP_LOCK_REQUIRED;
1506         ObjectRef *ref = checkobject(L, 1);
1507         RemotePlayer *player = getplayer(ref);
1508         if (player == NULL)
1509                 return 0;
1510
1511         u32 id = -1;
1512         if (!lua_isnil(L, 2))
1513                 id = lua_tonumber(L, 2);
1514
1515         if (!getServer(L)->hudRemove(player, id))
1516                 return 0;
1517
1518         lua_pushboolean(L, true);
1519         return 1;
1520 }
1521
1522 // hud_change(self, id, stat, data)
1523 int ObjectRef::l_hud_change(lua_State *L)
1524 {
1525         NO_MAP_LOCK_REQUIRED;
1526         ObjectRef *ref = checkobject(L, 1);
1527         RemotePlayer *player = getplayer(ref);
1528         if (player == NULL)
1529                 return 0;
1530
1531         u32 id = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : -1;
1532
1533         HudElement *e = player->getHud(id);
1534         if (!e)
1535                 return 0;
1536
1537         void *value = NULL;
1538         HudElementStat stat = read_hud_change(L, e, &value);
1539
1540         getServer(L)->hudChange(player, id, stat, value);
1541
1542         lua_pushboolean(L, true);
1543         return 1;
1544 }
1545
1546 // hud_get(self, id)
1547 int ObjectRef::l_hud_get(lua_State *L)
1548 {
1549         NO_MAP_LOCK_REQUIRED;
1550         ObjectRef *ref = checkobject(L, 1);
1551         RemotePlayer *player = getplayer(ref);
1552         if (player == NULL)
1553                 return 0;
1554
1555         u32 id = lua_tonumber(L, -1);
1556
1557         HudElement *e = player->getHud(id);
1558         if (!e)
1559                 return 0;
1560         push_hud_element(L, e);
1561         return 1;
1562 }
1563
1564 // hud_set_flags(self, flags)
1565 int ObjectRef::l_hud_set_flags(lua_State *L)
1566 {
1567         NO_MAP_LOCK_REQUIRED;
1568         ObjectRef *ref = checkobject(L, 1);
1569         RemotePlayer *player = getplayer(ref);
1570         if (player == NULL)
1571                 return 0;
1572
1573         u32 flags = 0;
1574         u32 mask  = 0;
1575         bool flag;
1576
1577         const EnumString *esp = es_HudBuiltinElement;
1578         for (int i = 0; esp[i].str; i++) {
1579                 if (getboolfield(L, 2, esp[i].str, flag)) {
1580                         flags |= esp[i].num * flag;
1581                         mask  |= esp[i].num;
1582                 }
1583         }
1584         if (!getServer(L)->hudSetFlags(player, flags, mask))
1585                 return 0;
1586
1587         lua_pushboolean(L, true);
1588         return 1;
1589 }
1590
1591 int ObjectRef::l_hud_get_flags(lua_State *L)
1592 {
1593         NO_MAP_LOCK_REQUIRED;
1594         ObjectRef *ref = checkobject(L, 1);
1595         RemotePlayer *player = getplayer(ref);
1596         if (player == NULL)
1597                 return 0;
1598
1599         lua_newtable(L);
1600         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE);
1601         lua_setfield(L, -2, "hotbar");
1602         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE);
1603         lua_setfield(L, -2, "healthbar");
1604         lua_pushboolean(L, player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE);
1605         lua_setfield(L, -2, "crosshair");
1606         lua_pushboolean(L, player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE);
1607         lua_setfield(L, -2, "wielditem");
1608         lua_pushboolean(L, player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE);
1609         lua_setfield(L, -2, "breathbar");
1610         lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
1611         lua_setfield(L, -2, "minimap");
1612         lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE);
1613         lua_setfield(L, -2, "minimap_radar");
1614
1615         return 1;
1616 }
1617
1618 // hud_set_hotbar_itemcount(self, hotbar_itemcount)
1619 int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
1620 {
1621         NO_MAP_LOCK_REQUIRED;
1622         ObjectRef *ref = checkobject(L, 1);
1623         RemotePlayer *player = getplayer(ref);
1624         if (player == NULL)
1625                 return 0;
1626
1627         s32 hotbar_itemcount = lua_tonumber(L, 2);
1628
1629         if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
1630                 return 0;
1631
1632         lua_pushboolean(L, true);
1633         return 1;
1634 }
1635
1636 // hud_get_hotbar_itemcount(self)
1637 int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
1638 {
1639         NO_MAP_LOCK_REQUIRED;
1640         ObjectRef *ref = checkobject(L, 1);
1641         RemotePlayer *player = getplayer(ref);
1642         if (player == NULL)
1643                 return 0;
1644
1645         lua_pushnumber(L, player->getHotbarItemcount());
1646         return 1;
1647 }
1648
1649 // hud_set_hotbar_image(self, name)
1650 int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
1651 {
1652         NO_MAP_LOCK_REQUIRED;
1653         ObjectRef *ref = checkobject(L, 1);
1654         RemotePlayer *player = getplayer(ref);
1655         if (player == NULL)
1656                 return 0;
1657
1658         std::string name = readParam<std::string>(L, 2);
1659
1660         getServer(L)->hudSetHotbarImage(player, name);
1661         return 1;
1662 }
1663
1664 // hud_get_hotbar_image(self)
1665 int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
1666 {
1667         NO_MAP_LOCK_REQUIRED;
1668         ObjectRef *ref = checkobject(L, 1);
1669         RemotePlayer *player = getplayer(ref);
1670         if (player == NULL)
1671                 return 0;
1672
1673         const std::string &name = player->getHotbarImage();
1674         lua_pushlstring(L, name.c_str(), name.size());
1675         return 1;
1676 }
1677
1678 // hud_set_hotbar_selected_image(self, name)
1679 int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
1680 {
1681         NO_MAP_LOCK_REQUIRED;
1682         ObjectRef *ref = checkobject(L, 1);
1683         RemotePlayer *player = getplayer(ref);
1684         if (player == NULL)
1685                 return 0;
1686
1687         std::string name = readParam<std::string>(L, 2);
1688
1689         getServer(L)->hudSetHotbarSelectedImage(player, name);
1690         return 1;
1691 }
1692
1693 // hud_get_hotbar_selected_image(self)
1694 int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
1695 {
1696         NO_MAP_LOCK_REQUIRED;
1697         ObjectRef *ref = checkobject(L, 1);
1698         RemotePlayer *player = getplayer(ref);
1699         if (player == NULL)
1700                 return 0;
1701
1702         const std::string &name = player->getHotbarSelectedImage();
1703         lua_pushlstring(L, name.c_str(), name.size());
1704         return 1;
1705 }
1706
1707 // set_sky(self, {base_color=, type=, textures=, clouds=, sky_colors={}})
1708 int ObjectRef::l_set_sky(lua_State *L)
1709 {
1710         NO_MAP_LOCK_REQUIRED;
1711         ObjectRef *ref = checkobject(L, 1);
1712         RemotePlayer *player = getplayer(ref);
1713         if (!player)
1714                 return 0;
1715
1716         bool is_colorspec = is_color_table(L, 2);
1717
1718         SkyboxParams skybox_params = player->getSkyParams();
1719         if (lua_istable(L, 2) && !is_colorspec) {
1720                 lua_getfield(L, 2, "base_color");
1721                 if (!lua_isnil(L, -1))
1722                         read_color(L, -1, &skybox_params.bgcolor);
1723                 lua_pop(L, 1);
1724
1725                 lua_getfield(L, 2, "type");
1726                 if (!lua_isnil(L, -1))
1727                         skybox_params.type = luaL_checkstring(L, -1);
1728                 lua_pop(L, 1);
1729
1730                 lua_getfield(L, 2, "textures");
1731                 skybox_params.textures.clear();
1732                 if (lua_istable(L, -1) && skybox_params.type == "skybox") {
1733                         lua_pushnil(L);
1734                         while (lua_next(L, -2) != 0) {
1735                                 // Key is at index -2 and value at index -1
1736                                 skybox_params.textures.emplace_back(readParam<std::string>(L, -1));
1737                                 // Removes the value, but keeps the key for iteration
1738                                 lua_pop(L, 1);
1739                         }
1740                 }
1741                 lua_pop(L, 1);
1742
1743                 /*
1744                 We want to avoid crashes, so we're checking even if we're not using them.
1745                 However, we want to ensure that the skybox can be set to nil when
1746                 using "regular" or "plain" skybox modes as textures aren't needed.
1747                 */
1748
1749                 if (skybox_params.textures.size() != 6 && skybox_params.textures.size() > 0)
1750                         throw LuaError("Skybox expects 6 textures!");
1751
1752                 skybox_params.clouds = getboolfield_default(L, 2,
1753                         "clouds", skybox_params.clouds);
1754
1755                 lua_getfield(L, 2, "sky_color");
1756                 if (lua_istable(L, -1)) {
1757                         lua_getfield(L, -1, "day_sky");
1758                         read_color(L, -1, &skybox_params.sky_color.day_sky);
1759                         lua_pop(L, 1);
1760
1761                         lua_getfield(L, -1, "day_horizon");
1762                         read_color(L, -1, &skybox_params.sky_color.day_horizon);
1763                         lua_pop(L, 1);
1764
1765                         lua_getfield(L, -1, "dawn_sky");
1766                         read_color(L, -1, &skybox_params.sky_color.dawn_sky);
1767                         lua_pop(L, 1);
1768
1769                         lua_getfield(L, -1, "dawn_horizon");
1770                         read_color(L, -1, &skybox_params.sky_color.dawn_horizon);
1771                         lua_pop(L, 1);
1772
1773                         lua_getfield(L, -1, "night_sky");
1774                         read_color(L, -1, &skybox_params.sky_color.night_sky);
1775                         lua_pop(L, 1);
1776
1777                         lua_getfield(L, -1, "night_horizon");
1778                         read_color(L, -1, &skybox_params.sky_color.night_horizon);
1779                         lua_pop(L, 1);
1780
1781                         lua_getfield(L, -1, "indoors");
1782                         read_color(L, -1, &skybox_params.sky_color.indoors);
1783                         lua_pop(L, 1);
1784
1785                         // Prevent flickering clouds at dawn/dusk:
1786                         skybox_params.fog_sun_tint = video::SColor(255, 255, 255, 255);
1787                         lua_getfield(L, -1, "fog_sun_tint");
1788                         read_color(L, -1, &skybox_params.fog_sun_tint);
1789                         lua_pop(L, 1);
1790
1791                         skybox_params.fog_moon_tint = video::SColor(255, 255, 255, 255);
1792                         lua_getfield(L, -1, "fog_moon_tint");
1793                         read_color(L, -1, &skybox_params.fog_moon_tint);
1794                         lua_pop(L, 1);
1795
1796                         lua_getfield(L, -1, "fog_tint_type");
1797                         if (!lua_isnil(L, -1))
1798                                 skybox_params.fog_tint_type = luaL_checkstring(L, -1);
1799                         lua_pop(L, 1);
1800
1801                         // Because we need to leave the "sky_color" table.
1802                         lua_pop(L, 1);
1803                 }
1804         } else {
1805                 // Handle old set_sky calls, and log deprecated:
1806                 log_deprecated(L, "Deprecated call to set_sky, please check lua_api.txt");
1807
1808                 // Fix sun, moon and stars showing when classic textured skyboxes are used
1809                 SunParams sun_params = player->getSunParams();
1810                 MoonParams moon_params = player->getMoonParams();
1811                 StarParams star_params = player->getStarParams();
1812
1813                 // Prevent erroneous background colors
1814                 skybox_params.bgcolor = video::SColor(255, 255, 255, 255);
1815                 read_color(L, 2, &skybox_params.bgcolor);
1816
1817                 skybox_params.type = luaL_checkstring(L, 3);
1818
1819                 // Preserve old behaviour of the sun, moon and stars
1820                 // when using the old set_sky call.
1821                 if (skybox_params.type == "regular") {
1822                         sun_params.visible = true;
1823                         sun_params.sunrise_visible = true;
1824                         moon_params.visible = true;
1825                         star_params.visible = true;
1826                 } else {
1827                         sun_params.visible = false;
1828                         sun_params.sunrise_visible = false;
1829                         moon_params.visible = false;
1830                         star_params.visible = false;
1831                 }
1832
1833                 skybox_params.textures.clear();
1834                 if (lua_istable(L, 4)) {
1835                         lua_pushnil(L);
1836                         while (lua_next(L, 4) != 0) {
1837                         // Key at index -2, and value at index -1
1838                                 if (lua_isstring(L, -1))
1839                                         skybox_params.textures.emplace_back(readParam<std::string>(L, -1));
1840                                 else
1841                                         skybox_params.textures.emplace_back("");
1842                                 // Remove the value, keep the key for the next iteration
1843                                 lua_pop(L, 1);
1844                         }
1845                 }
1846                 if (skybox_params.type == "skybox" && skybox_params.textures.size() != 6)
1847                         throw LuaError("Skybox expects 6 textures.");
1848
1849                 skybox_params.clouds = true;
1850                 if (lua_isboolean(L, 5))
1851                         skybox_params.clouds = readParam<bool>(L, 5);
1852
1853                 getServer(L)->setSun(player, sun_params);
1854                 getServer(L)->setMoon(player, moon_params);
1855                 getServer(L)->setStars(player, star_params);
1856         }
1857         getServer(L)->setSky(player, skybox_params);
1858         lua_pushboolean(L, true);
1859         return 1;
1860 }
1861
1862 // get_sky(self)
1863 int ObjectRef::l_get_sky(lua_State *L)
1864 {
1865         NO_MAP_LOCK_REQUIRED;
1866         ObjectRef *ref = checkobject(L, 1);
1867         RemotePlayer *player = getplayer(ref);
1868
1869         if (!player)
1870                 return 0;
1871         SkyboxParams skybox_params;
1872         skybox_params = player->getSkyParams();
1873
1874         push_ARGB8(L, skybox_params.bgcolor);
1875         lua_pushlstring(L, skybox_params.type.c_str(), skybox_params.type.size());
1876
1877         lua_newtable(L);
1878         s16 i = 1;
1879         for (const std::string& texture : skybox_params.textures) {
1880                 lua_pushlstring(L, texture.c_str(), texture.size());
1881                 lua_rawseti(L, -2, i++);
1882         }
1883         lua_pushboolean(L, skybox_params.clouds);
1884         return 4;
1885 }
1886
1887 // get_sky_color(self)
1888 int ObjectRef::l_get_sky_color(lua_State *L)
1889 {
1890         NO_MAP_LOCK_REQUIRED;
1891         ObjectRef *ref = checkobject(L, 1);
1892         RemotePlayer *player = getplayer(ref);
1893
1894         if (!player)
1895                 return 0;
1896
1897         const SkyboxParams& skybox_params = player->getSkyParams();
1898
1899         lua_newtable(L);
1900         if (skybox_params.type == "regular") {
1901                 push_ARGB8(L, skybox_params.sky_color.day_sky);
1902                 lua_setfield(L, -2, "day_sky");
1903                 push_ARGB8(L, skybox_params.sky_color.day_horizon);
1904                 lua_setfield(L, -2, "day_horizon");
1905                 push_ARGB8(L, skybox_params.sky_color.dawn_sky);
1906                 lua_setfield(L, -2, "dawn_sky");
1907                 push_ARGB8(L, skybox_params.sky_color.dawn_horizon);
1908                 lua_setfield(L, -2, "dawn_horizon");
1909                 push_ARGB8(L, skybox_params.sky_color.night_sky);
1910                 lua_setfield(L, -2, "night_sky");
1911                 push_ARGB8(L, skybox_params.sky_color.night_horizon);
1912                 lua_setfield(L, -2, "night_horizon");
1913                 push_ARGB8(L, skybox_params.sky_color.indoors);
1914                 lua_setfield(L, -2, "indoors");
1915         }
1916         push_ARGB8(L, skybox_params.fog_sun_tint);
1917         lua_setfield(L, -2, "fog_sun_tint");
1918         push_ARGB8(L, skybox_params.fog_moon_tint);
1919         lua_setfield(L, -2, "fog_moon_tint");
1920         lua_pushstring(L, skybox_params.fog_tint_type.c_str());
1921         lua_setfield(L, -2, "fog_tint_type");
1922         return 1;
1923 }
1924
1925 // set_sun(self, {visible, texture=, tonemap=, sunrise=, rotation=, scale=})
1926 int ObjectRef::l_set_sun(lua_State *L)
1927 {
1928         NO_MAP_LOCK_REQUIRED;
1929         ObjectRef *ref = checkobject(L, 1);
1930         RemotePlayer *player = getplayer(ref);
1931         if (!player)
1932                 return 0;
1933
1934         if (!lua_istable(L, 2))
1935                 return 0;
1936
1937         SunParams sun_params = player->getSunParams();
1938
1939         sun_params.visible = getboolfield_default(L, 2,
1940                         "visible", sun_params.visible);
1941         sun_params.texture = getstringfield_default(L, 2,
1942                         "texture", sun_params.texture);
1943         sun_params.tonemap = getstringfield_default(L, 2,
1944                         "tonemap", sun_params.tonemap);
1945         sun_params.sunrise = getstringfield_default(L, 2,
1946                         "sunrise", sun_params.sunrise);
1947         sun_params.sunrise_visible = getboolfield_default(L, 2,
1948                         "sunrise_visible", sun_params.sunrise_visible);
1949         sun_params.scale = getfloatfield_default(L, 2,
1950                         "scale", sun_params.scale);
1951
1952         getServer(L)->setSun(player, sun_params);
1953         lua_pushboolean(L, true);
1954         return 1;
1955 }
1956
1957 //get_sun(self)
1958 int ObjectRef::l_get_sun(lua_State *L)
1959 {
1960         NO_MAP_LOCK_REQUIRED;
1961         ObjectRef *ref = checkobject(L, 1);
1962         RemotePlayer *player = getplayer(ref);
1963         if (!player)
1964                 return 0;
1965         const SunParams &sun_params = player->getSunParams();
1966
1967         lua_newtable(L);
1968         lua_pushboolean(L, sun_params.visible);
1969         lua_setfield(L, -2, "visible");
1970         lua_pushstring(L, sun_params.texture.c_str());
1971         lua_setfield(L, -2, "texture");
1972         lua_pushstring(L, sun_params.tonemap.c_str());
1973         lua_setfield(L, -2, "tonemap");
1974         lua_pushstring(L, sun_params.sunrise.c_str());
1975         lua_setfield(L, -2, "sunrise");
1976         lua_pushboolean(L, sun_params.sunrise_visible);
1977         lua_setfield(L, -2, "sunrise_visible");
1978         lua_pushnumber(L, sun_params.scale);
1979         lua_setfield(L, -2, "scale");
1980
1981         return 1;
1982 }
1983
1984 // set_moon(self, {visible, texture=, tonemap=, sunrise=, rotation=, scale=})
1985 int ObjectRef::l_set_moon(lua_State *L)
1986 {
1987         NO_MAP_LOCK_REQUIRED;
1988         ObjectRef *ref = checkobject(L, 1);
1989         RemotePlayer *player = getplayer(ref);
1990         if (!player)
1991                 return 0;
1992         if (!lua_istable(L, 2))
1993                 return 0;
1994
1995         MoonParams moon_params = player->getMoonParams();
1996
1997         moon_params.visible = getboolfield_default(L, 2,
1998                 "visible", moon_params.visible);
1999         moon_params.texture = getstringfield_default(L, 2,
2000                 "texture", moon_params.texture);
2001         moon_params.tonemap = getstringfield_default(L, 2,
2002                 "tonemap", moon_params.tonemap);
2003         moon_params.scale = getfloatfield_default(L, 2,
2004                 "scale", moon_params.scale);
2005
2006         getServer(L)->setMoon(player, moon_params);
2007         lua_pushboolean(L, true);
2008         return 1;
2009 }
2010
2011 // get_moon(self)
2012 int ObjectRef::l_get_moon(lua_State *L)
2013 {
2014         NO_MAP_LOCK_REQUIRED;
2015         ObjectRef *ref = checkobject(L, 1);
2016         RemotePlayer *player = getplayer(ref);
2017         if (!player)
2018                 return 0;
2019         const MoonParams &moon_params = player->getMoonParams();
2020
2021         lua_newtable(L);
2022         lua_pushboolean(L, moon_params.visible);
2023         lua_setfield(L, -2, "visible");
2024         lua_pushstring(L, moon_params.texture.c_str());
2025         lua_setfield(L, -2, "texture");
2026         lua_pushstring(L, moon_params.tonemap.c_str());
2027         lua_setfield(L, -2, "tonemap");
2028         lua_pushnumber(L, moon_params.scale);
2029         lua_setfield(L, -2, "scale");
2030
2031         return 1;
2032 }
2033
2034 // set_stars(self, {visible, count=, starcolor=, rotation=, scale=})
2035 int ObjectRef::l_set_stars(lua_State *L)
2036 {
2037         NO_MAP_LOCK_REQUIRED;
2038         ObjectRef *ref = checkobject(L, 1);
2039         RemotePlayer *player = getplayer(ref);
2040         if (!player)
2041                 return 0;
2042         if (!lua_istable(L, 2))
2043                 return 0;
2044
2045         StarParams star_params = player->getStarParams();
2046
2047         star_params.visible = getboolfield_default(L, 2,
2048                 "visible", star_params.visible);
2049         star_params.count = getintfield_default(L, 2,
2050                 "count", star_params.count);
2051
2052         lua_getfield(L, 2, "star_color");
2053         if (!lua_isnil(L, -1))
2054                 read_color(L, -1, &star_params.starcolor);
2055         lua_pop(L, 1);
2056
2057         star_params.scale = getfloatfield_default(L, 2,
2058                 "scale", star_params.scale);
2059
2060         getServer(L)->setStars(player, star_params);
2061         lua_pushboolean(L, true);
2062         return 1;
2063 }
2064
2065 // get_stars(self)
2066 int ObjectRef::l_get_stars(lua_State *L)
2067 {
2068         NO_MAP_LOCK_REQUIRED;
2069         ObjectRef *ref = checkobject(L, 1);
2070         RemotePlayer *player = getplayer(ref);
2071         if (!player)
2072                 return 0;
2073         const StarParams &star_params = player->getStarParams();
2074
2075         lua_newtable(L);
2076         lua_pushboolean(L, star_params.visible);
2077         lua_setfield(L, -2, "visible");
2078         lua_pushnumber(L, star_params.count);
2079         lua_setfield(L, -2, "count");
2080         push_ARGB8(L, star_params.starcolor);
2081         lua_setfield(L, -2, "star_color");
2082         lua_pushnumber(L, star_params.scale);
2083         lua_setfield(L, -2, "scale");
2084
2085         return 1;
2086 }
2087
2088 // set_clouds(self, {density=, color=, ambient=, height=, thickness=, speed=})
2089 int ObjectRef::l_set_clouds(lua_State *L)
2090 {
2091         NO_MAP_LOCK_REQUIRED;
2092         ObjectRef *ref = checkobject(L, 1);
2093         RemotePlayer *player = getplayer(ref);
2094         if (!player)
2095                 return 0;
2096         if (!lua_istable(L, 2))
2097                 return 0;
2098
2099         CloudParams cloud_params = player->getCloudParams();
2100
2101         cloud_params.density = getfloatfield_default(L, 2, "density", cloud_params.density);
2102
2103         lua_getfield(L, 2, "color");
2104         if (!lua_isnil(L, -1))
2105                 read_color(L, -1, &cloud_params.color_bright);
2106         lua_pop(L, 1);
2107         lua_getfield(L, 2, "ambient");
2108         if (!lua_isnil(L, -1))
2109                 read_color(L, -1, &cloud_params.color_ambient);
2110         lua_pop(L, 1);
2111
2112         cloud_params.height    = getfloatfield_default(L, 2, "height",    cloud_params.height   );
2113         cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness);
2114
2115         lua_getfield(L, 2, "speed");
2116         if (lua_istable(L, -1)) {
2117                 v2f new_speed;
2118                 new_speed.X = getfloatfield_default(L, -1, "x", 0);
2119                 new_speed.Y = getfloatfield_default(L, -1, "z", 0);
2120                 cloud_params.speed = new_speed;
2121         }
2122         lua_pop(L, 1);
2123
2124         getServer(L)->setClouds(player, cloud_params);
2125         lua_pushboolean(L, true);
2126         return 1;
2127 }
2128
2129 int ObjectRef::l_get_clouds(lua_State *L)
2130 {
2131         NO_MAP_LOCK_REQUIRED;
2132         ObjectRef *ref = checkobject(L, 1);
2133         RemotePlayer *player = getplayer(ref);
2134         if (!player)
2135                 return 0;
2136         const CloudParams &cloud_params = player->getCloudParams();
2137
2138         lua_newtable(L);
2139         lua_pushnumber(L, cloud_params.density);
2140         lua_setfield(L, -2, "density");
2141         push_ARGB8(L, cloud_params.color_bright);
2142         lua_setfield(L, -2, "color");
2143         push_ARGB8(L, cloud_params.color_ambient);
2144         lua_setfield(L, -2, "ambient");
2145         lua_pushnumber(L, cloud_params.height);
2146         lua_setfield(L, -2, "height");
2147         lua_pushnumber(L, cloud_params.thickness);
2148         lua_setfield(L, -2, "thickness");
2149         lua_newtable(L);
2150         lua_pushnumber(L, cloud_params.speed.X);
2151         lua_setfield(L, -2, "x");
2152         lua_pushnumber(L, cloud_params.speed.Y);
2153         lua_setfield(L, -2, "y");
2154         lua_setfield(L, -2, "speed");
2155
2156         return 1;
2157 }
2158
2159
2160 // override_day_night_ratio(self, brightness=0...1)
2161 int ObjectRef::l_override_day_night_ratio(lua_State *L)
2162 {
2163         NO_MAP_LOCK_REQUIRED;
2164         ObjectRef *ref = checkobject(L, 1);
2165         RemotePlayer *player = getplayer(ref);
2166         if (player == NULL)
2167                 return 0;
2168
2169         bool do_override = false;
2170         float ratio = 0.0f;
2171         if (!lua_isnil(L, 2)) {
2172                 do_override = true;
2173                 ratio = readParam<float>(L, 2);
2174         }
2175
2176         getServer(L)->overrideDayNightRatio(player, do_override, ratio);
2177         lua_pushboolean(L, true);
2178         return 1;
2179 }
2180
2181 // get_day_night_ratio(self)
2182 int ObjectRef::l_get_day_night_ratio(lua_State *L)
2183 {
2184         NO_MAP_LOCK_REQUIRED;
2185         ObjectRef *ref = checkobject(L, 1);
2186         RemotePlayer *player = getplayer(ref);
2187         if (player == NULL)
2188                 return 0;
2189
2190         bool do_override;
2191         float ratio;
2192         player->getDayNightRatio(&do_override, &ratio);
2193
2194         if (do_override)
2195                 lua_pushnumber(L, ratio);
2196         else
2197                 lua_pushnil(L);
2198
2199         return 1;
2200 }
2201
2202 ObjectRef::ObjectRef(ServerActiveObject *object):
2203         m_object(object)
2204 {
2205         //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
2206 }
2207
2208 // Creates an ObjectRef and leaves it on top of stack
2209 // Not callable from Lua; all references are created on the C side.
2210 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
2211 {
2212         ObjectRef *o = new ObjectRef(object);
2213         //infostream<<"ObjectRef::create: o="<<o<<std::endl;
2214         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2215         luaL_getmetatable(L, className);
2216         lua_setmetatable(L, -2);
2217 }
2218
2219 void ObjectRef::set_null(lua_State *L)
2220 {
2221         ObjectRef *o = checkobject(L, -1);
2222         o->m_object = NULL;
2223 }
2224
2225 void ObjectRef::Register(lua_State *L)
2226 {
2227         lua_newtable(L);
2228         int methodtable = lua_gettop(L);
2229         luaL_newmetatable(L, className);
2230         int metatable = lua_gettop(L);
2231
2232         lua_pushliteral(L, "__metatable");
2233         lua_pushvalue(L, methodtable);
2234         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
2235
2236         lua_pushliteral(L, "__index");
2237         lua_pushvalue(L, methodtable);
2238         lua_settable(L, metatable);
2239
2240         lua_pushliteral(L, "__gc");
2241         lua_pushcfunction(L, gc_object);
2242         lua_settable(L, metatable);
2243
2244         lua_pop(L, 1);  // drop metatable
2245
2246         markAliasDeprecated(methods);
2247         luaL_openlib(L, 0, methods, 0);  // fill methodtable
2248         lua_pop(L, 1);  // drop methodtable
2249
2250         // Cannot be created from Lua
2251         //lua_register(L, className, create_object);
2252 }
2253
2254 const char ObjectRef::className[] = "ObjectRef";
2255 luaL_Reg ObjectRef::methods[] = {
2256         // ServerActiveObject
2257         luamethod(ObjectRef, remove),
2258         luamethod_aliased(ObjectRef, get_pos, getpos),
2259         luamethod_aliased(ObjectRef, set_pos, setpos),
2260         luamethod_aliased(ObjectRef, move_to, moveto),
2261         luamethod(ObjectRef, punch),
2262         luamethod(ObjectRef, right_click),
2263         luamethod(ObjectRef, set_hp),
2264         luamethod(ObjectRef, get_hp),
2265         luamethod(ObjectRef, get_inventory),
2266         luamethod(ObjectRef, get_wield_list),
2267         luamethod(ObjectRef, get_wield_index),
2268         luamethod(ObjectRef, get_wielded_item),
2269         luamethod(ObjectRef, set_wielded_item),
2270         luamethod(ObjectRef, set_armor_groups),
2271         luamethod(ObjectRef, get_armor_groups),
2272         luamethod(ObjectRef, set_animation),
2273         luamethod(ObjectRef, get_animation),
2274         luamethod(ObjectRef, set_animation_frame_speed),
2275         luamethod(ObjectRef, set_bone_position),
2276         luamethod(ObjectRef, get_bone_position),
2277         luamethod(ObjectRef, set_attach),
2278         luamethod(ObjectRef, get_attach),
2279         luamethod(ObjectRef, set_detach),
2280         luamethod(ObjectRef, set_properties),
2281         luamethod(ObjectRef, get_properties),
2282         luamethod(ObjectRef, set_nametag_attributes),
2283         luamethod(ObjectRef, get_nametag_attributes),
2284         // LuaEntitySAO-only
2285         luamethod_aliased(ObjectRef, set_velocity, setvelocity),
2286         luamethod(ObjectRef, add_velocity),
2287         luamethod_aliased(ObjectRef, get_velocity, getvelocity),
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_aliased(ObjectRef, set_sprite, setsprite),
2296         luamethod(ObjectRef, get_entity_name),
2297         luamethod(ObjectRef, get_luaentity),
2298         // Player-only
2299         luamethod(ObjectRef, is_player),
2300         luamethod(ObjectRef, is_player_connected),
2301         luamethod(ObjectRef, get_player_name),
2302         luamethod(ObjectRef, get_player_velocity),
2303         luamethod(ObjectRef, add_player_velocity),
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 };