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