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