]> git.lizzy.rs Git - minetest.git/blob - src/script/lua_api/l_object.cpp
Allow saturation to be controlled by the server. (#13075)
[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 ServerActiveObject* ObjectRef::getobject(ObjectRef *ref)
44 {
45         ServerActiveObject *sao = ref->m_object;
46         if (sao && sao->isGone())
47                 return nullptr;
48         return sao;
49 }
50
51 LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
52 {
53         ServerActiveObject *sao = getobject(ref);
54         if (sao == nullptr)
55                 return nullptr;
56         if (sao->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
57                 return nullptr;
58         return (LuaEntitySAO*)sao;
59 }
60
61 PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
62 {
63         ServerActiveObject *sao = getobject(ref);
64         if (sao == nullptr)
65                 return nullptr;
66         if (sao->getType() != ACTIVEOBJECT_TYPE_PLAYER)
67                 return nullptr;
68         return (PlayerSAO*)sao;
69 }
70
71 RemotePlayer *ObjectRef::getplayer(ObjectRef *ref)
72 {
73         PlayerSAO *playersao = getplayersao(ref);
74         if (playersao == nullptr)
75                 return nullptr;
76         return playersao->getPlayer();
77 }
78
79 // Exported functions
80
81 // garbage collector
82 int ObjectRef::gc_object(lua_State *L) {
83         ObjectRef *obj = *(ObjectRef **)(lua_touserdata(L, 1));
84         delete obj;
85         return 0;
86 }
87
88 // remove(self)
89 int ObjectRef::l_remove(lua_State *L)
90 {
91         GET_ENV_PTR;
92
93         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
94         ServerActiveObject *sao = getobject(ref);
95         if (sao == nullptr)
96                 return 0;
97         if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER)
98                 return 0;
99
100         sao->clearChildAttachments();
101         sao->clearParentAttachment();
102
103         verbosestream << "ObjectRef::l_remove(): id=" << sao->getId() << std::endl;
104         sao->markForRemoval();
105         return 0;
106 }
107
108 // get_pos(self)
109 int ObjectRef::l_get_pos(lua_State *L)
110 {
111         NO_MAP_LOCK_REQUIRED;
112         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
113         ServerActiveObject *sao = getobject(ref);
114         if (sao == nullptr)
115                 return 0;
116
117         push_v3f(L, sao->getBasePosition() / BS);
118         return 1;
119 }
120
121 // set_pos(self, pos)
122 int ObjectRef::l_set_pos(lua_State *L)
123 {
124         NO_MAP_LOCK_REQUIRED;
125         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
126         ServerActiveObject *sao = getobject(ref);
127         if (sao == nullptr)
128                 return 0;
129
130         v3f pos = checkFloatPos(L, 2);
131
132         sao->setPos(pos);
133         return 0;
134 }
135
136 // move_to(self, pos, continuous)
137 int ObjectRef::l_move_to(lua_State *L)
138 {
139         NO_MAP_LOCK_REQUIRED;
140         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
141         ServerActiveObject *sao = getobject(ref);
142         if (sao == nullptr)
143                 return 0;
144
145         v3f pos = checkFloatPos(L, 2);
146         bool continuous = readParam<bool>(L, 3);
147
148         sao->moveTo(pos, continuous);
149         return 0;
150 }
151
152 // punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
153 int ObjectRef::l_punch(lua_State *L)
154 {
155         NO_MAP_LOCK_REQUIRED;
156         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
157         ObjectRef *puncher_ref = checkObject<ObjectRef>(L, 2);
158         ServerActiveObject *sao = getobject(ref);
159         ServerActiveObject *puncher = getobject(puncher_ref);
160         if (sao == nullptr || puncher == nullptr)
161                 return 0;
162
163         float time_from_last_punch = readParam<float>(L, 3, 1000000.0f);
164         ToolCapabilities toolcap = read_tool_capabilities(L, 4);
165         v3f dir = readParam<v3f>(L, 5, sao->getBasePosition() - puncher->getBasePosition());
166         dir.normalize();
167
168         u32 wear = sao->punch(dir, &toolcap, puncher, time_from_last_punch);
169         lua_pushnumber(L, wear);
170
171         return 1;
172 }
173
174 // right_click(self, clicker)
175 int ObjectRef::l_right_click(lua_State *L)
176 {
177         NO_MAP_LOCK_REQUIRED;
178         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
179         ObjectRef *ref2 = checkObject<ObjectRef>(L, 2);
180         ServerActiveObject *sao = getobject(ref);
181         ServerActiveObject *sao2 = getobject(ref2);
182         if (sao == nullptr || sao2 == nullptr)
183                 return 0;
184
185         sao->rightClick(sao2);
186         return 0;
187 }
188
189 // set_hp(self, hp, reason)
190 int ObjectRef::l_set_hp(lua_State *L)
191 {
192         NO_MAP_LOCK_REQUIRED;
193         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
194         ServerActiveObject *sao = getobject(ref);
195         if (sao == nullptr)
196                 return 0;
197
198         int hp = readParam<float>(L, 2);
199         PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP);
200
201         reason.from_mod = true;
202         if (lua_istable(L, 3)) {
203                 lua_pushvalue(L, 3);
204
205                 lua_getfield(L, -1, "type");
206                 if (lua_isstring(L, -1) &&
207                                 !reason.setTypeFromString(readParam<std::string>(L, -1))) {
208                         errorstream << "Bad type given!" << std::endl;
209                 }
210                 lua_pop(L, 1);
211
212                 reason.lua_reference = luaL_ref(L, LUA_REGISTRYINDEX);
213         }
214
215         sao->setHP(hp, reason);
216         if (reason.hasLuaReference())
217                 luaL_unref(L, LUA_REGISTRYINDEX, reason.lua_reference);
218         return 0;
219 }
220
221 // get_hp(self)
222 int ObjectRef::l_get_hp(lua_State *L)
223 {
224         NO_MAP_LOCK_REQUIRED;
225         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
226         ServerActiveObject *sao = getobject(ref);
227         if (sao == nullptr) {
228                 // Default hp is 1
229                 lua_pushnumber(L, 1);
230                 return 1;
231         }
232
233         int hp = sao->getHP();
234
235         lua_pushnumber(L, hp);
236         return 1;
237 }
238
239 // get_inventory(self)
240 int ObjectRef::l_get_inventory(lua_State *L)
241 {
242         NO_MAP_LOCK_REQUIRED;
243         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
244         ServerActiveObject *sao = getobject(ref);
245         if (sao == nullptr)
246                 return 0;
247
248         InventoryLocation loc = sao->getInventoryLocation();
249         if (getServerInventoryMgr(L)->getInventory(loc) != nullptr)
250                 InvRef::create(L, loc);
251         else
252                 lua_pushnil(L); // An object may have no inventory (nil)
253         return 1;
254 }
255
256 // get_wield_list(self)
257 int ObjectRef::l_get_wield_list(lua_State *L)
258 {
259         NO_MAP_LOCK_REQUIRED;
260         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
261         ServerActiveObject *sao = getobject(ref);
262         if (sao == nullptr)
263                 return 0;
264
265         lua_pushstring(L, sao->getWieldList().c_str());
266         return 1;
267 }
268
269 // get_wield_index(self)
270 int ObjectRef::l_get_wield_index(lua_State *L)
271 {
272         NO_MAP_LOCK_REQUIRED;
273         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
274         ServerActiveObject *sao = getobject(ref);
275         if (sao == nullptr)
276                 return 0;
277
278         lua_pushinteger(L, sao->getWieldIndex() + 1);
279         return 1;
280 }
281
282 // get_wielded_item(self)
283 int ObjectRef::l_get_wielded_item(lua_State *L)
284 {
285         NO_MAP_LOCK_REQUIRED;
286         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
287         ServerActiveObject *sao = getobject(ref);
288         if (sao == nullptr) {
289                 // Empty ItemStack
290                 LuaItemStack::create(L, ItemStack());
291                 return 1;
292         }
293
294         ItemStack selected_item;
295         sao->getWieldedItem(&selected_item, nullptr);
296         LuaItemStack::create(L, selected_item);
297         return 1;
298 }
299
300 // set_wielded_item(self, item)
301 int ObjectRef::l_set_wielded_item(lua_State *L)
302 {
303         NO_MAP_LOCK_REQUIRED;
304         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
305         ServerActiveObject *sao = getobject(ref);
306         if (sao == nullptr)
307                 return 0;
308
309         ItemStack item = read_item(L, 2, getServer(L)->idef());
310
311         bool success = sao->setWieldedItem(item);
312         if (success && sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
313                 getServer(L)->SendInventory((PlayerSAO *)sao, true);
314         }
315         lua_pushboolean(L, success);
316         return 1;
317 }
318
319 // set_armor_groups(self, groups)
320 int ObjectRef::l_set_armor_groups(lua_State *L)
321 {
322         NO_MAP_LOCK_REQUIRED;
323         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
324         ServerActiveObject *sao = getobject(ref);
325         if (sao == nullptr)
326                 return 0;
327
328         ItemGroupList groups;
329
330         read_groups(L, 2, groups);
331         if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
332                 if (!g_settings->getBool("enable_damage") && !itemgroup_get(groups, "immortal")) {
333                         warningstream << "Mod tried to enable damage for a player, but it's "
334                                 "disabled globally. Ignoring." << std::endl;
335                         infostream << script_get_backtrace(L) << std::endl;
336                         groups["immortal"] = 1;
337                 }
338         }
339
340         sao->setArmorGroups(groups);
341         return 0;
342 }
343
344 // get_armor_groups(self)
345 int ObjectRef::l_get_armor_groups(lua_State *L)
346 {
347         NO_MAP_LOCK_REQUIRED;
348         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
349         ServerActiveObject *sao = getobject(ref);
350         if (sao == nullptr)
351                 return 0;
352
353         push_groups(L, sao->getArmorGroups());
354         return 1;
355 }
356
357 // set_animation(self, frame_range, frame_speed, frame_blend, frame_loop)
358 int ObjectRef::l_set_animation(lua_State *L)
359 {
360         NO_MAP_LOCK_REQUIRED;
361         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
362         ServerActiveObject *sao = getobject(ref);
363         if (sao == nullptr)
364                 return 0;
365
366         v2f frame_range   = readParam<v2f>(L,  2, v2f(1, 1));
367         float frame_speed = readParam<float>(L, 3, 15.0f);
368         float frame_blend = readParam<float>(L, 4, 0.0f);
369         bool frame_loop   = readParam<bool>(L, 5, true);
370
371         sao->setAnimation(frame_range, frame_speed, frame_blend, frame_loop);
372         return 0;
373 }
374
375 // get_animation(self)
376 int ObjectRef::l_get_animation(lua_State *L)
377 {
378         NO_MAP_LOCK_REQUIRED;
379         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
380         ServerActiveObject *sao = getobject(ref);
381         if (sao == nullptr)
382                 return 0;
383
384         v2f frames = v2f(1, 1);
385         float frame_speed = 15;
386         float frame_blend = 0;
387         bool frame_loop = true;
388
389         sao->getAnimation(&frames, &frame_speed, &frame_blend, &frame_loop);
390         push_v2f(L, frames);
391         lua_pushnumber(L, frame_speed);
392         lua_pushnumber(L, frame_blend);
393         lua_pushboolean(L, frame_loop);
394         return 4;
395 }
396
397 // set_local_animation(self, idle, walk, dig, walk_while_dig, frame_speed)
398 int ObjectRef::l_set_local_animation(lua_State *L)
399 {
400         NO_MAP_LOCK_REQUIRED;
401         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
402         RemotePlayer *player = getplayer(ref);
403         if (player == nullptr)
404                 return 0;
405
406         v2s32 frames[4];
407         for (int i=0;i<4;i++) {
408                 if (!lua_isnil(L, 2+1))
409                         frames[i] = read_v2s32(L, 2+i);
410         }
411         float frame_speed = readParam<float>(L, 6, 30.0f);
412
413         getServer(L)->setLocalPlayerAnimations(player, frames, frame_speed);
414         return 0;
415 }
416
417 // get_local_animation(self)
418 int ObjectRef::l_get_local_animation(lua_State *L)
419 {
420         NO_MAP_LOCK_REQUIRED;
421         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
422         RemotePlayer *player = getplayer(ref);
423         if (player == nullptr)
424                 return 0;
425
426         v2s32 frames[4];
427         float frame_speed;
428         player->getLocalAnimations(frames, &frame_speed);
429
430         for (const v2s32 &frame : frames) {
431                 push_v2s32(L, frame);
432         }
433
434         lua_pushnumber(L, frame_speed);
435         return 5;
436 }
437
438 // set_eye_offset(self, firstperson, thirdperson)
439 int ObjectRef::l_set_eye_offset(lua_State *L)
440 {
441         NO_MAP_LOCK_REQUIRED;
442         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
443         RemotePlayer *player = getplayer(ref);
444         if (player == nullptr)
445                 return 0;
446
447         v3f offset_first = readParam<v3f>(L, 2, v3f(0, 0, 0));
448         v3f offset_third = readParam<v3f>(L, 3, v3f(0, 0, 0));
449
450         // Prevent abuse of offset values (keep player always visible)
451         offset_third.X = rangelim(offset_third.X,-10,10);
452         offset_third.Z = rangelim(offset_third.Z,-5,5);
453         /* TODO: if possible: improve the camera collision detection to allow Y <= -1.5) */
454         offset_third.Y = rangelim(offset_third.Y,-10,15); //1.5*BS
455
456         getServer(L)->setPlayerEyeOffset(player, offset_first, offset_third);
457         return 0;
458 }
459
460 // get_eye_offset(self)
461 int ObjectRef::l_get_eye_offset(lua_State *L)
462 {
463         NO_MAP_LOCK_REQUIRED;
464         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
465         RemotePlayer *player = getplayer(ref);
466         if (player == nullptr)
467                 return 0;
468
469         push_v3f(L, player->eye_offset_first);
470         push_v3f(L, player->eye_offset_third);
471         return 2;
472 }
473
474 // send_mapblock(self, pos)
475 int ObjectRef::l_send_mapblock(lua_State *L)
476 {
477         NO_MAP_LOCK_REQUIRED;
478         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
479         RemotePlayer *player = getplayer(ref);
480         if (player == nullptr)
481                 return 0;
482
483         v3s16 pos = read_v3s16(L, 2);
484
485         session_t peer_id = player->getPeerId();
486         bool r = getServer(L)->SendBlock(peer_id, pos);
487
488         lua_pushboolean(L, r);
489         return 1;
490 }
491
492 // set_animation_frame_speed(self, frame_speed)
493 int ObjectRef::l_set_animation_frame_speed(lua_State *L)
494 {
495         NO_MAP_LOCK_REQUIRED;
496         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
497         ServerActiveObject *sao = getobject(ref);
498         if (sao == nullptr)
499                 return 0;
500
501         if (!lua_isnil(L, 2)) {
502                 float frame_speed = readParam<float>(L, 2);
503                 sao->setAnimationSpeed(frame_speed);
504                 lua_pushboolean(L, true);
505         } else {
506                 lua_pushboolean(L, false);
507         }
508         return 1;
509 }
510
511 // set_bone_position(self, bone, position, rotation)
512 int ObjectRef::l_set_bone_position(lua_State *L)
513 {
514         NO_MAP_LOCK_REQUIRED;
515         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
516         ServerActiveObject *sao = getobject(ref);
517         if (sao == nullptr)
518                 return 0;
519
520         std::string bone = readParam<std::string>(L, 2, "");
521         v3f position = readParam<v3f>(L, 3, v3f(0, 0, 0));
522         v3f rotation = readParam<v3f>(L, 4, v3f(0, 0, 0));
523
524         sao->setBonePosition(bone, position, rotation);
525         return 0;
526 }
527
528 // get_bone_position(self, bone)
529 int ObjectRef::l_get_bone_position(lua_State *L)
530 {
531         NO_MAP_LOCK_REQUIRED;
532         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
533         ServerActiveObject *sao = getobject(ref);
534         if (sao == nullptr)
535                 return 0;
536
537         std::string bone = readParam<std::string>(L, 2, "");
538
539         v3f position = v3f(0, 0, 0);
540         v3f rotation = v3f(0, 0, 0);
541         sao->getBonePosition(bone, &position, &rotation);
542
543         push_v3f(L, position);
544         push_v3f(L, rotation);
545         return 2;
546 }
547
548 // set_attach(self, parent, bone, position, rotation, force_visible)
549 int ObjectRef::l_set_attach(lua_State *L)
550 {
551         GET_ENV_PTR;
552         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
553         ObjectRef *parent_ref = checkObject<ObjectRef>(L, 2);
554         ServerActiveObject *sao = getobject(ref);
555         ServerActiveObject *parent = getobject(parent_ref);
556         if (sao == nullptr || parent == nullptr)
557                 return 0;
558         if (sao == parent)
559                 throw LuaError("ObjectRef::set_attach: attaching object to itself is not allowed.");
560
561         int parent_id;
562         std::string bone;
563         v3f position;
564         v3f rotation;
565         bool force_visible;
566
567         sao->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible);
568         if (parent_id) {
569                 ServerActiveObject *old_parent = env->getActiveObject(parent_id);
570                 old_parent->removeAttachmentChild(sao->getId());
571         }
572
573         bone          = readParam<std::string>(L, 3, "");
574         position      = readParam<v3f>(L, 4, v3f(0, 0, 0));
575         rotation      = readParam<v3f>(L, 5, v3f(0, 0, 0));
576         force_visible = readParam<bool>(L, 6, false);
577
578         sao->setAttachment(parent->getId(), bone, position, rotation, force_visible);
579         parent->addAttachmentChild(sao->getId());
580         return 0;
581 }
582
583 // get_attach(self)
584 int ObjectRef::l_get_attach(lua_State *L)
585 {
586         GET_ENV_PTR;
587         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
588         ServerActiveObject *sao = getobject(ref);
589         if (sao == nullptr)
590                 return 0;
591
592         int parent_id;
593         std::string bone;
594         v3f position;
595         v3f rotation;
596         bool force_visible;
597
598         sao->getAttachment(&parent_id, &bone, &position, &rotation, &force_visible);
599         if (parent_id == 0)
600                 return 0;
601
602         ServerActiveObject *parent = env->getActiveObject(parent_id);
603         getScriptApiBase(L)->objectrefGetOrCreate(L, parent);
604         lua_pushlstring(L, bone.c_str(), bone.size());
605         push_v3f(L, position);
606         push_v3f(L, rotation);
607         lua_pushboolean(L, force_visible);
608         return 5;
609 }
610
611 // get_children(self)
612 int ObjectRef::l_get_children(lua_State *L)
613 {
614         GET_ENV_PTR;
615         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
616         ServerActiveObject *sao = getobject(ref);
617         if (sao == nullptr)
618                 return 0;
619
620         const std::unordered_set<int> child_ids = sao->getAttachmentChildIds();
621         int i = 0;
622
623         lua_createtable(L, child_ids.size(), 0);
624         for (const int id : child_ids) {
625                 ServerActiveObject *child = env->getActiveObject(id);
626                 getScriptApiBase(L)->objectrefGetOrCreate(L, child);
627                 lua_rawseti(L, -2, ++i);
628         }
629         return 1;
630 }
631
632 // set_detach(self)
633 int ObjectRef::l_set_detach(lua_State *L)
634 {
635         GET_ENV_PTR;
636         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
637         ServerActiveObject *sao = getobject(ref);
638         if (sao == nullptr)
639                 return 0;
640
641         sao->clearParentAttachment();
642         return 0;
643 }
644
645 // set_properties(self, properties)
646 int ObjectRef::l_set_properties(lua_State *L)
647 {
648         NO_MAP_LOCK_REQUIRED;
649         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
650         ServerActiveObject *sao = getobject(ref);
651         if (sao == nullptr)
652                 return 0;
653
654         ObjectProperties *prop = sao->accessObjectProperties();
655         if (prop == nullptr)
656                 return 0;
657
658         read_object_properties(L, 2, sao, prop, getServer(L)->idef());
659         prop->validate();
660         sao->notifyObjectPropertiesModified();
661         return 0;
662 }
663
664 // get_properties(self)
665 int ObjectRef::l_get_properties(lua_State *L)
666 {
667         NO_MAP_LOCK_REQUIRED;
668         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
669         ServerActiveObject *sao = getobject(ref);
670         if (sao == nullptr)
671                 return 0;
672
673         ObjectProperties *prop = sao->accessObjectProperties();
674         if (prop == nullptr)
675                 return 0;
676
677         push_object_properties(L, prop);
678         return 1;
679 }
680
681 // is_player(self)
682 int ObjectRef::l_is_player(lua_State *L)
683 {
684         NO_MAP_LOCK_REQUIRED;
685         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
686         RemotePlayer *player = getplayer(ref);
687         lua_pushboolean(L, (player != nullptr));
688         return 1;
689 }
690
691 // set_nametag_attributes(self, attributes)
692 int ObjectRef::l_set_nametag_attributes(lua_State *L)
693 {
694         NO_MAP_LOCK_REQUIRED;
695         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
696         ServerActiveObject *sao = getobject(ref);
697         if (sao == nullptr)
698                 return 0;
699
700         ObjectProperties *prop = sao->accessObjectProperties();
701         if (prop == nullptr)
702                 return 0;
703
704         lua_getfield(L, 2, "color");
705         if (!lua_isnil(L, -1)) {
706                 video::SColor color = prop->nametag_color;
707                 read_color(L, -1, &color);
708                 prop->nametag_color = color;
709         }
710         lua_pop(L, 1);
711
712         lua_getfield(L, -1, "bgcolor");
713         if (!lua_isnil(L, -1)) {
714                 if (lua_toboolean(L, -1)) {
715                         video::SColor color;
716                         if (read_color(L, -1, &color))
717                                 prop->nametag_bgcolor = color;
718                 } else {
719                         prop->nametag_bgcolor = nullopt;
720                 }
721         }
722         lua_pop(L, 1);
723
724         prop->nametag = getstringfield_default(L, 2, "text", prop->nametag);
725
726         prop->validate();
727         sao->notifyObjectPropertiesModified();
728         return 0;
729 }
730
731 // get_nametag_attributes(self)
732 int ObjectRef::l_get_nametag_attributes(lua_State *L)
733 {
734         NO_MAP_LOCK_REQUIRED;
735         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
736         ServerActiveObject *sao = getobject(ref);
737         if (sao == nullptr)
738                 return 0;
739
740         ObjectProperties *prop = sao->accessObjectProperties();
741         if (!prop)
742                 return 0;
743
744         lua_newtable(L);
745
746         push_ARGB8(L, prop->nametag_color);
747         lua_setfield(L, -2, "color");
748
749         if (prop->nametag_bgcolor) {
750                 push_ARGB8(L, prop->nametag_bgcolor.value());
751                 lua_setfield(L, -2, "bgcolor");
752         } else {
753                 lua_pushboolean(L, false);
754                 lua_setfield(L, -2, "bgcolor");
755         }
756
757         lua_pushstring(L, prop->nametag.c_str());
758         lua_setfield(L, -2, "text");
759
760
761
762         return 1;
763 }
764
765 /* LuaEntitySAO-only */
766
767 // set_velocity(self, velocity)
768 int ObjectRef::l_set_velocity(lua_State *L)
769 {
770         NO_MAP_LOCK_REQUIRED;
771         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
772         LuaEntitySAO *sao = getluaobject(ref);
773         if (sao == nullptr)
774                 return 0;
775
776         v3f vel = checkFloatPos(L, 2);
777
778         sao->setVelocity(vel);
779         return 0;
780 }
781
782 // add_velocity(self, velocity)
783 int ObjectRef::l_add_velocity(lua_State *L)
784 {
785         NO_MAP_LOCK_REQUIRED;
786         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
787         ServerActiveObject *sao = getobject(ref);
788         if (sao == nullptr)
789                 return 0;
790
791         v3f vel = checkFloatPos(L, 2);
792
793         if (sao->getType() == ACTIVEOBJECT_TYPE_LUAENTITY) {
794                 LuaEntitySAO *entitysao = dynamic_cast<LuaEntitySAO*>(sao);
795                 entitysao->addVelocity(vel);
796         } else if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
797                 PlayerSAO *playersao = dynamic_cast<PlayerSAO*>(sao);
798                 playersao->setMaxSpeedOverride(vel);
799                 getServer(L)->SendPlayerSpeed(playersao->getPeerID(), vel);
800         }
801
802         return 0;
803 }
804
805 // get_velocity(self)
806 int ObjectRef::l_get_velocity(lua_State *L)
807 {
808         NO_MAP_LOCK_REQUIRED;
809         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
810         ServerActiveObject *sao = getobject(ref);
811         if (sao == nullptr)
812                 return 0;
813
814         if (sao->getType() == ACTIVEOBJECT_TYPE_LUAENTITY) {
815                 LuaEntitySAO *entitysao = dynamic_cast<LuaEntitySAO*>(sao);
816                 v3f vel = entitysao->getVelocity();
817                 pushFloatPos(L, vel);
818                 return 1;
819         } else if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
820                 RemotePlayer *player = dynamic_cast<PlayerSAO*>(sao)->getPlayer();
821                 push_v3f(L, player->getSpeed() / BS);
822                 return 1;
823         }
824
825         lua_pushnil(L);
826         return 1;
827 }
828
829 // set_acceleration(self, acceleration)
830 int ObjectRef::l_set_acceleration(lua_State *L)
831 {
832         NO_MAP_LOCK_REQUIRED;
833         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
834         LuaEntitySAO *entitysao = getluaobject(ref);
835         if (entitysao == nullptr)
836                 return 0;
837
838         v3f acceleration = checkFloatPos(L, 2);
839
840         entitysao->setAcceleration(acceleration);
841         return 0;
842 }
843
844 // get_acceleration(self)
845 int ObjectRef::l_get_acceleration(lua_State *L)
846 {
847         NO_MAP_LOCK_REQUIRED;
848         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
849         LuaEntitySAO *entitysao = getluaobject(ref);
850         if (entitysao == nullptr)
851                 return 0;
852
853         v3f acceleration = entitysao->getAcceleration();
854         pushFloatPos(L, acceleration);
855         return 1;
856 }
857
858 // set_rotation(self, rotation)
859 int ObjectRef::l_set_rotation(lua_State *L)
860 {
861         NO_MAP_LOCK_REQUIRED;
862         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
863         LuaEntitySAO *entitysao = getluaobject(ref);
864         if (entitysao == nullptr)
865                 return 0;
866
867         v3f rotation = check_v3f(L, 2) * core::RADTODEG;
868
869         entitysao->setRotation(rotation);
870         return 0;
871 }
872
873 // get_rotation(self)
874 int ObjectRef::l_get_rotation(lua_State *L)
875 {
876         NO_MAP_LOCK_REQUIRED;
877         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
878         LuaEntitySAO *entitysao = getluaobject(ref);
879         if (entitysao == nullptr)
880                 return 0;
881
882         v3f rotation = entitysao->getRotation() * core::DEGTORAD;
883
884         lua_newtable(L);
885         push_v3f(L, rotation);
886         return 1;
887 }
888
889 // set_yaw(self, yaw)
890 int ObjectRef::l_set_yaw(lua_State *L)
891 {
892         NO_MAP_LOCK_REQUIRED;
893         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
894         LuaEntitySAO *entitysao = getluaobject(ref);
895         if (entitysao == nullptr)
896                 return 0;
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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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 0;
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<ObjectRef>(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 0;
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<ObjectRef>(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 0;
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<ObjectRef>(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 0;
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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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<ObjectRef>(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         return 0;
1301 }
1302
1303 // get_inventory_formspec(self) -> formspec
1304 int ObjectRef::l_get_inventory_formspec(lua_State *L)
1305 {
1306         NO_MAP_LOCK_REQUIRED;
1307         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1308         RemotePlayer *player = getplayer(ref);
1309         if (player == nullptr)
1310                 return 0;
1311
1312         std::string formspec = player->inventory_formspec;
1313
1314         lua_pushlstring(L, formspec.c_str(), formspec.size());
1315         return 1;
1316 }
1317
1318 // set_formspec_prepend(self, formspec)
1319 int ObjectRef::l_set_formspec_prepend(lua_State *L)
1320 {
1321         NO_MAP_LOCK_REQUIRED;
1322         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1323         RemotePlayer *player = getplayer(ref);
1324         if (player == nullptr)
1325                 return 0;
1326
1327         std::string formspec = luaL_checkstring(L, 2);
1328
1329         player->formspec_prepend = formspec;
1330         getServer(L)->reportFormspecPrependModified(player->getName());
1331         return 0;
1332 }
1333
1334 // get_formspec_prepend(self)
1335 int ObjectRef::l_get_formspec_prepend(lua_State *L)
1336 {
1337         NO_MAP_LOCK_REQUIRED;
1338         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1339         RemotePlayer *player = getplayer(ref);
1340         if (player == nullptr)
1341                  return 0;
1342
1343         std::string formspec = player->formspec_prepend;
1344
1345         lua_pushlstring(L, formspec.c_str(), formspec.size());
1346         return 1;
1347 }
1348
1349 // get_player_control(self)
1350 int ObjectRef::l_get_player_control(lua_State *L)
1351 {
1352         NO_MAP_LOCK_REQUIRED;
1353         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1354         RemotePlayer *player = getplayer(ref);
1355
1356         lua_newtable(L);
1357         if (player == nullptr)
1358                 return 1;
1359
1360         const PlayerControl &control = player->getPlayerControl();
1361         lua_pushboolean(L, control.direction_keys & (1 << 0));
1362         lua_setfield(L, -2, "up");
1363         lua_pushboolean(L, control.direction_keys & (1 << 1));
1364         lua_setfield(L, -2, "down");
1365         lua_pushboolean(L, control.direction_keys & (1 << 2));
1366         lua_setfield(L, -2, "left");
1367         lua_pushboolean(L, control.direction_keys & (1 << 3));
1368         lua_setfield(L, -2, "right");
1369         lua_pushboolean(L, control.jump);
1370         lua_setfield(L, -2, "jump");
1371         lua_pushboolean(L, control.aux1);
1372         lua_setfield(L, -2, "aux1");
1373         lua_pushboolean(L, control.sneak);
1374         lua_setfield(L, -2, "sneak");
1375         lua_pushboolean(L, control.dig);
1376         lua_setfield(L, -2, "dig");
1377         lua_pushboolean(L, control.place);
1378         lua_setfield(L, -2, "place");
1379         // Legacy fields to ensure mod compatibility
1380         lua_pushboolean(L, control.dig);
1381         lua_setfield(L, -2, "LMB");
1382         lua_pushboolean(L, control.place);
1383         lua_setfield(L, -2, "RMB");
1384         lua_pushboolean(L, control.zoom);
1385         lua_setfield(L, -2, "zoom");
1386         return 1;
1387 }
1388
1389 // get_player_control_bits(self)
1390 int ObjectRef::l_get_player_control_bits(lua_State *L)
1391 {
1392         NO_MAP_LOCK_REQUIRED;
1393         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1394         RemotePlayer *player = getplayer(ref);
1395         if (player == nullptr) {
1396                 lua_pushinteger(L, 0);
1397                 return 1;
1398         }
1399
1400         const auto &c = player->getPlayerControl();
1401
1402         // This is very close to PlayerControl::getKeysPressed() but duplicated
1403         // here so the encoding in the API is not inadvertedly changed.
1404         u32 keypress_bits =
1405                 c.direction_keys |
1406                 ( (u32)(c.jump  & 1) << 4) |
1407                 ( (u32)(c.aux1  & 1) << 5) |
1408                 ( (u32)(c.sneak & 1) << 6) |
1409                 ( (u32)(c.dig   & 1) << 7) |
1410                 ( (u32)(c.place & 1) << 8) |
1411                 ( (u32)(c.zoom  & 1) << 9)
1412         ;
1413
1414         lua_pushinteger(L, keypress_bits);
1415         return 1;
1416 }
1417
1418 // set_physics_override(self, override_table)
1419 int ObjectRef::l_set_physics_override(lua_State *L)
1420 {
1421         NO_MAP_LOCK_REQUIRED;
1422         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1423         PlayerSAO *playersao = getplayersao(ref);
1424         if (playersao == nullptr)
1425                 return 0;
1426
1427         RemotePlayer *player = playersao->getPlayer();
1428         auto &phys = player->physics_override;
1429
1430         if (lua_istable(L, 2)) {
1431                 bool modified = false;
1432                 modified |= getfloatfield(L, 2, "speed", phys.speed);
1433                 modified |= getfloatfield(L, 2, "jump", phys.jump);
1434                 modified |= getfloatfield(L, 2, "gravity", phys.gravity);
1435                 modified |= getboolfield(L, 2, "sneak", phys.sneak);
1436                 modified |= getboolfield(L, 2, "sneak_glitch", phys.sneak_glitch);
1437                 modified |= getboolfield(L, 2, "new_move", phys.new_move);
1438                 if (modified)
1439                         playersao->m_physics_override_sent = false;
1440         } else {
1441                 // old, non-table format
1442                 // TODO: Remove this code after version 5.4.0
1443                 log_deprecated(L, "Deprecated use of set_physics_override(num, num, num)");
1444
1445                 if (!lua_isnil(L, 2)) {
1446                         phys.speed = lua_tonumber(L, 2);
1447                         playersao->m_physics_override_sent = false;
1448                 }
1449                 if (!lua_isnil(L, 3)) {
1450                         phys.jump = lua_tonumber(L, 3);
1451                         playersao->m_physics_override_sent = false;
1452                 }
1453                 if (!lua_isnil(L, 4)) {
1454                         phys.gravity = lua_tonumber(L, 4);
1455                         playersao->m_physics_override_sent = false;
1456                 }
1457         }
1458         return 0;
1459 }
1460
1461 // get_physics_override(self)
1462 int ObjectRef::l_get_physics_override(lua_State *L)
1463 {
1464         NO_MAP_LOCK_REQUIRED;
1465         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1466         RemotePlayer *player = getplayer(ref);
1467         if (player == nullptr)
1468                 return 0;
1469
1470         const auto &phys = player->physics_override;
1471         lua_newtable(L);
1472         lua_pushnumber(L, phys.speed);
1473         lua_setfield(L, -2, "speed");
1474         lua_pushnumber(L, phys.jump);
1475         lua_setfield(L, -2, "jump");
1476         lua_pushnumber(L, phys.gravity);
1477         lua_setfield(L, -2, "gravity");
1478         lua_pushboolean(L, phys.sneak);
1479         lua_setfield(L, -2, "sneak");
1480         lua_pushboolean(L, phys.sneak_glitch);
1481         lua_setfield(L, -2, "sneak_glitch");
1482         lua_pushboolean(L, phys.new_move);
1483         lua_setfield(L, -2, "new_move");
1484         return 1;
1485 }
1486
1487 // hud_add(self, hud)
1488 int ObjectRef::l_hud_add(lua_State *L)
1489 {
1490         NO_MAP_LOCK_REQUIRED;
1491         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1492         RemotePlayer *player = getplayer(ref);
1493         if (player == nullptr)
1494                 return 0;
1495
1496         HudElement *elem = new HudElement;
1497         read_hud_element(L, elem);
1498
1499         u32 id = getServer(L)->hudAdd(player, elem);
1500         if (id == U32_MAX) {
1501                 delete elem;
1502                 return 0;
1503         }
1504
1505         lua_pushnumber(L, id);
1506         return 1;
1507 }
1508
1509 // hud_remove(self, id)
1510 int ObjectRef::l_hud_remove(lua_State *L)
1511 {
1512         NO_MAP_LOCK_REQUIRED;
1513         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1514         RemotePlayer *player = getplayer(ref);
1515         if (player == nullptr)
1516                 return 0;
1517
1518         u32 id = luaL_checkint(L, 2);
1519
1520         if (!getServer(L)->hudRemove(player, id))
1521                 return 0;
1522
1523         lua_pushboolean(L, true);
1524         return 1;
1525 }
1526
1527 // hud_change(self, id, stat, data)
1528 int ObjectRef::l_hud_change(lua_State *L)
1529 {
1530         NO_MAP_LOCK_REQUIRED;
1531         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1532         RemotePlayer *player = getplayer(ref);
1533         if (player == nullptr)
1534                 return 0;
1535
1536         u32 id = luaL_checkint(L, 2);
1537
1538         HudElement *elem = player->getHud(id);
1539         if (elem == nullptr)
1540                 return 0;
1541
1542         HudElementStat stat;
1543         void *value = nullptr;
1544         bool ok = read_hud_change(L, stat, elem, &value);
1545
1546         if (ok)
1547                 getServer(L)->hudChange(player, id, stat, value);
1548
1549         lua_pushboolean(L, ok);
1550         return 1;
1551 }
1552
1553 // hud_get(self, id)
1554 int ObjectRef::l_hud_get(lua_State *L)
1555 {
1556         NO_MAP_LOCK_REQUIRED;
1557         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1558         RemotePlayer *player = getplayer(ref);
1559         if (player == nullptr)
1560                 return 0;
1561
1562         u32 id = luaL_checkint(L, 2);
1563
1564         HudElement *elem = player->getHud(id);
1565         if (elem == nullptr)
1566                 return 0;
1567
1568         push_hud_element(L, elem);
1569         return 1;
1570 }
1571
1572 // hud_set_flags(self, flags)
1573 int ObjectRef::l_hud_set_flags(lua_State *L)
1574 {
1575         NO_MAP_LOCK_REQUIRED;
1576         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1577         RemotePlayer *player = getplayer(ref);
1578         if (player == nullptr)
1579                 return 0;
1580
1581         u32 flags = 0;
1582         u32 mask  = 0;
1583         bool flag;
1584
1585         const EnumString *esp = es_HudBuiltinElement;
1586         for (int i = 0; esp[i].str; i++) {
1587                 if (getboolfield(L, 2, esp[i].str, flag)) {
1588                         flags |= esp[i].num * flag;
1589                         mask  |= esp[i].num;
1590                 }
1591         }
1592         if (!getServer(L)->hudSetFlags(player, flags, mask))
1593                 return 0;
1594
1595         return 0;
1596 }
1597
1598 // hud_get_flags(self)
1599 int ObjectRef::l_hud_get_flags(lua_State *L)
1600 {
1601         NO_MAP_LOCK_REQUIRED;
1602         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1603         RemotePlayer *player = getplayer(ref);
1604         if (player == nullptr)
1605                 return 0;
1606
1607         lua_newtable(L);
1608         const EnumString *esp = es_HudBuiltinElement;
1609         for (int i = 0; esp[i].str; i++) {
1610                 lua_pushboolean(L, (player->hud_flags & esp[i].num) != 0);
1611                 lua_setfield(L, -2, esp[i].str);
1612         }
1613         return 1;
1614 }
1615
1616 // hud_set_hotbar_itemcount(self, hotbar_itemcount)
1617 int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
1618 {
1619         NO_MAP_LOCK_REQUIRED;
1620         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1621         RemotePlayer *player = getplayer(ref);
1622         if (player == nullptr)
1623                 return 0;
1624
1625         s32 hotbar_itemcount = luaL_checkint(L, 2);
1626
1627         if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
1628                 return 0;
1629
1630         lua_pushboolean(L, true);
1631         return 1;
1632 }
1633
1634 // hud_get_hotbar_itemcount(self)
1635 int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
1636 {
1637         NO_MAP_LOCK_REQUIRED;
1638         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1639         RemotePlayer *player = getplayer(ref);
1640         if (player == nullptr)
1641                 return 0;
1642
1643         lua_pushnumber(L, player->getHotbarItemcount());
1644         return 1;
1645 }
1646
1647 // hud_set_hotbar_image(self, name)
1648 int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
1649 {
1650         NO_MAP_LOCK_REQUIRED;
1651         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1652         RemotePlayer *player = getplayer(ref);
1653         if (player == nullptr)
1654                 return 0;
1655
1656         std::string name = readParam<std::string>(L, 2);
1657
1658         getServer(L)->hudSetHotbarImage(player, name);
1659         return 1;
1660 }
1661
1662 // hud_get_hotbar_image(self)
1663 int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
1664 {
1665         NO_MAP_LOCK_REQUIRED;
1666         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1667         RemotePlayer *player = getplayer(ref);
1668         if (player == nullptr)
1669                 return 0;
1670
1671         const std::string &name = player->getHotbarImage();
1672
1673         lua_pushlstring(L, name.c_str(), name.size());
1674         return 1;
1675 }
1676
1677 // hud_set_hotbar_selected_image(self, name)
1678 int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
1679 {
1680         NO_MAP_LOCK_REQUIRED;
1681         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1682         RemotePlayer *player = getplayer(ref);
1683         if (player == nullptr)
1684                 return 0;
1685
1686         std::string name = readParam<std::string>(L, 2);
1687
1688         getServer(L)->hudSetHotbarSelectedImage(player, name);
1689         return 1;
1690 }
1691
1692 // hud_get_hotbar_selected_image(self)
1693 int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
1694 {
1695         NO_MAP_LOCK_REQUIRED;
1696         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1697         RemotePlayer *player = getplayer(ref);
1698         if (player == nullptr)
1699                 return 0;
1700
1701         const std::string &name = player->getHotbarSelectedImage();
1702
1703         lua_pushlstring(L, name.c_str(), name.size());
1704         return 1;
1705 }
1706
1707 // set_sky(self, sky_parameters)
1708 int ObjectRef::l_set_sky(lua_State *L)
1709 {
1710         NO_MAP_LOCK_REQUIRED;
1711         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1712         RemotePlayer *player = getplayer(ref);
1713         if (player == nullptr)
1714                 return 0;
1715
1716         SkyboxParams sky_params = player->getSkyParams();
1717
1718         // reset if empty
1719         if (lua_isnoneornil(L, 2) && lua_isnone(L, 3)) {
1720                 sky_params = SkyboxDefaults::getSkyDefaults();
1721         } else if (lua_istable(L, 2) && !is_color_table(L, 2)) {
1722                 lua_getfield(L, 2, "base_color");
1723                 if (!lua_isnil(L, -1))
1724                         read_color(L, -1, &sky_params.bgcolor);
1725                 lua_pop(L, 1);
1726
1727                 lua_getfield(L, 2, "type");
1728                 if (!lua_isnil(L, -1))
1729                         sky_params.type = luaL_checkstring(L, -1);
1730                 lua_pop(L, 1);
1731
1732                 lua_getfield(L, 2, "textures");
1733                 sky_params.textures.clear();
1734                 if (lua_istable(L, -1) && sky_params.type == "skybox") {
1735                         lua_pushnil(L);
1736                         while (lua_next(L, -2) != 0) {
1737                                 // Key is at index -2 and value at index -1
1738                                 sky_params.textures.emplace_back(readParam<std::string>(L, -1));
1739                                 // Removes the value, but keeps the key for iteration
1740                                 lua_pop(L, 1);
1741                         }
1742                 }
1743                 lua_pop(L, 1);
1744
1745                 // Validate that we either have six or zero textures
1746                 if (sky_params.textures.size() != 6 && !sky_params.textures.empty())
1747                         throw LuaError("Skybox expects 6 textures!");
1748
1749                 sky_params.clouds = getboolfield_default(L, 2, "clouds", sky_params.clouds);
1750
1751                 lua_getfield(L, 2, "sky_color");
1752                 if (lua_istable(L, -1)) {
1753                         lua_getfield(L, -1, "day_sky");
1754                         read_color(L, -1, &sky_params.sky_color.day_sky);
1755                         lua_pop(L, 1);
1756
1757                         lua_getfield(L, -1, "day_horizon");
1758                         read_color(L, -1, &sky_params.sky_color.day_horizon);
1759                         lua_pop(L, 1);
1760
1761                         lua_getfield(L, -1, "dawn_sky");
1762                         read_color(L, -1, &sky_params.sky_color.dawn_sky);
1763                         lua_pop(L, 1);
1764
1765                         lua_getfield(L, -1, "dawn_horizon");
1766                         read_color(L, -1, &sky_params.sky_color.dawn_horizon);
1767                         lua_pop(L, 1);
1768
1769                         lua_getfield(L, -1, "night_sky");
1770                         read_color(L, -1, &sky_params.sky_color.night_sky);
1771                         lua_pop(L, 1);
1772
1773                         lua_getfield(L, -1, "night_horizon");
1774                         read_color(L, -1, &sky_params.sky_color.night_horizon);
1775                         lua_pop(L, 1);
1776
1777                         lua_getfield(L, -1, "indoors");
1778                         read_color(L, -1, &sky_params.sky_color.indoors);
1779                         lua_pop(L, 1);
1780
1781                         // Prevent flickering clouds at dawn/dusk:
1782                         sky_params.fog_sun_tint = video::SColor(255, 255, 255, 255);
1783                         lua_getfield(L, -1, "fog_sun_tint");
1784                         read_color(L, -1, &sky_params.fog_sun_tint);
1785                         lua_pop(L, 1);
1786
1787                         sky_params.fog_moon_tint = video::SColor(255, 255, 255, 255);
1788                         lua_getfield(L, -1, "fog_moon_tint");
1789                         read_color(L, -1, &sky_params.fog_moon_tint);
1790                         lua_pop(L, 1);
1791
1792                         lua_getfield(L, -1, "fog_tint_type");
1793                         if (!lua_isnil(L, -1))
1794                                 sky_params.fog_tint_type = luaL_checkstring(L, -1);
1795                         lua_pop(L, 1);
1796
1797                         // pop "sky_color" table
1798                         lua_pop(L, 1);
1799                 }
1800         } else {
1801                 // Handle old set_sky calls, and log deprecated:
1802                 log_deprecated(L, "Deprecated call to set_sky, please check lua_api.txt");
1803
1804                 // Fix sun, moon and stars showing when classic textured skyboxes are used
1805                 SunParams sun_params = player->getSunParams();
1806                 MoonParams moon_params = player->getMoonParams();
1807                 StarParams star_params = player->getStarParams();
1808
1809                 // Prevent erroneous background colors
1810                 sky_params.bgcolor = video::SColor(255, 255, 255, 255);
1811                 read_color(L, 2, &sky_params.bgcolor);
1812
1813                 sky_params.type = luaL_checkstring(L, 3);
1814
1815                 // Preserve old behavior of the sun, moon and stars
1816                 // when using the old set_sky call.
1817                 if (sky_params.type == "regular") {
1818                         sun_params.visible = true;
1819                         sun_params.sunrise_visible = true;
1820                         moon_params.visible = true;
1821                         star_params.visible = true;
1822                 } else {
1823                         sun_params.visible = false;
1824                         sun_params.sunrise_visible = false;
1825                         moon_params.visible = false;
1826                         star_params.visible = false;
1827                 }
1828
1829                 sky_params.textures.clear();
1830                 if (lua_istable(L, 4)) {
1831                         lua_pushnil(L);
1832                         while (lua_next(L, 4) != 0) {
1833                                 // Key at index -2, and value at index -1
1834                                 sky_params.textures.emplace_back(readParam<std::string>(L, -1));
1835                                 // Remove the value, keep the key for the next iteration
1836                                 lua_pop(L, 1);
1837                         }
1838                 }
1839                 if (sky_params.type == "skybox" && sky_params.textures.size() != 6)
1840                         throw LuaError("Skybox expects 6 textures.");
1841
1842                 sky_params.clouds = true;
1843                 if (lua_isboolean(L, 5))
1844                         sky_params.clouds = readParam<bool>(L, 5);
1845
1846                 getServer(L)->setSun(player, sun_params);
1847                 getServer(L)->setMoon(player, moon_params);
1848                 getServer(L)->setStars(player, star_params);
1849         }
1850
1851         getServer(L)->setSky(player, sky_params);
1852         return 0;
1853 }
1854
1855 static void push_sky_color(lua_State *L, const SkyboxParams &params)
1856 {
1857         lua_newtable(L);
1858         if (params.type == "regular") {
1859                 push_ARGB8(L, params.sky_color.day_sky);
1860                 lua_setfield(L, -2, "day_sky");
1861                 push_ARGB8(L, params.sky_color.day_horizon);
1862                 lua_setfield(L, -2, "day_horizon");
1863                 push_ARGB8(L, params.sky_color.dawn_sky);
1864                 lua_setfield(L, -2, "dawn_sky");
1865                 push_ARGB8(L, params.sky_color.dawn_horizon);
1866                 lua_setfield(L, -2, "dawn_horizon");
1867                 push_ARGB8(L, params.sky_color.night_sky);
1868                 lua_setfield(L, -2, "night_sky");
1869                 push_ARGB8(L, params.sky_color.night_horizon);
1870                 lua_setfield(L, -2, "night_horizon");
1871                 push_ARGB8(L, params.sky_color.indoors);
1872                 lua_setfield(L, -2, "indoors");
1873         }
1874         push_ARGB8(L, params.fog_sun_tint);
1875         lua_setfield(L, -2, "fog_sun_tint");
1876         push_ARGB8(L, params.fog_moon_tint);
1877         lua_setfield(L, -2, "fog_moon_tint");
1878         lua_pushstring(L, params.fog_tint_type.c_str());
1879         lua_setfield(L, -2, "fog_tint_type");
1880 }
1881
1882 // get_sky(self, as_table)
1883 int ObjectRef::l_get_sky(lua_State *L)
1884 {
1885         NO_MAP_LOCK_REQUIRED;
1886         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1887         RemotePlayer *player = getplayer(ref);
1888         if (player == nullptr)
1889                 return 0;
1890
1891         const SkyboxParams &skybox_params = player->getSkyParams();
1892
1893         // handle the deprecated version
1894         if (!readParam<bool>(L, 2, false)) {
1895                 log_deprecated(L, "Deprecated call to get_sky, please check lua_api.txt");
1896
1897                 push_ARGB8(L, skybox_params.bgcolor);
1898                 lua_pushlstring(L, skybox_params.type.c_str(), skybox_params.type.size());
1899
1900                 lua_newtable(L);
1901                 s16 i = 1;
1902                 for (const std::string &texture : skybox_params.textures) {
1903                         lua_pushlstring(L, texture.c_str(), texture.size());
1904                         lua_rawseti(L, -2, i++);
1905                 }
1906                 lua_pushboolean(L, skybox_params.clouds);
1907                 return 4;
1908         }
1909
1910         lua_newtable(L);
1911         push_ARGB8(L, skybox_params.bgcolor);
1912         lua_setfield(L, -2, "base_color");
1913         lua_pushlstring(L, skybox_params.type.c_str(), skybox_params.type.size());
1914         lua_setfield(L, -2, "type");
1915
1916         lua_newtable(L);
1917         s16 i = 1;
1918         for (const std::string &texture : skybox_params.textures) {
1919                 lua_pushlstring(L, texture.c_str(), texture.size());
1920                 lua_rawseti(L, -2, i++);
1921         }
1922         lua_setfield(L, -2, "textures");
1923         lua_pushboolean(L, skybox_params.clouds);
1924         lua_setfield(L, -2, "clouds");
1925
1926         push_sky_color(L, skybox_params);
1927         lua_setfield(L, -2, "sky_color");
1928         return 1;
1929 }
1930
1931 // DEPRECATED
1932 // get_sky_color(self)
1933 int ObjectRef::l_get_sky_color(lua_State *L)
1934 {
1935         NO_MAP_LOCK_REQUIRED;
1936
1937         log_deprecated(L, "Deprecated call to get_sky_color, use get_sky instead");
1938
1939         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1940         RemotePlayer *player = getplayer(ref);
1941         if (player == nullptr)
1942                 return 0;
1943
1944         const SkyboxParams &skybox_params = player->getSkyParams();
1945         push_sky_color(L, skybox_params);
1946         return 1;
1947 }
1948
1949 // set_sun(self, sun_parameters)
1950 int ObjectRef::l_set_sun(lua_State *L)
1951 {
1952         NO_MAP_LOCK_REQUIRED;
1953         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1954         RemotePlayer *player = getplayer(ref);
1955         if (player == nullptr)
1956                 return 0;
1957
1958         SunParams sun_params = player->getSunParams();
1959
1960         // reset if empty
1961         if (lua_isnoneornil(L, 2)) {
1962                 sun_params = SkyboxDefaults::getSunDefaults();
1963         } else {
1964                 luaL_checktype(L, 2, LUA_TTABLE);
1965                 sun_params.visible = getboolfield_default(L, 2,   "visible", sun_params.visible);
1966                 sun_params.texture = getstringfield_default(L, 2, "texture", sun_params.texture);
1967                 sun_params.tonemap = getstringfield_default(L, 2, "tonemap", sun_params.tonemap);
1968                 sun_params.sunrise = getstringfield_default(L, 2, "sunrise", sun_params.sunrise);
1969                 sun_params.sunrise_visible = getboolfield_default(L, 2, "sunrise_visible", sun_params.sunrise_visible);
1970                 sun_params.scale   = getfloatfield_default(L, 2,  "scale",   sun_params.scale);
1971         }
1972
1973         getServer(L)->setSun(player, sun_params);
1974         return 0;
1975 }
1976
1977 //get_sun(self)
1978 int ObjectRef::l_get_sun(lua_State *L)
1979 {
1980         NO_MAP_LOCK_REQUIRED;
1981         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
1982         RemotePlayer *player = getplayer(ref);
1983         if (player == nullptr)
1984                 return 0;
1985
1986         const SunParams &sun_params = player->getSunParams();
1987
1988         lua_newtable(L);
1989         lua_pushboolean(L, sun_params.visible);
1990         lua_setfield(L, -2, "visible");
1991         lua_pushstring(L, sun_params.texture.c_str());
1992         lua_setfield(L, -2, "texture");
1993         lua_pushstring(L, sun_params.tonemap.c_str());
1994         lua_setfield(L, -2, "tonemap");
1995         lua_pushstring(L, sun_params.sunrise.c_str());
1996         lua_setfield(L, -2, "sunrise");
1997         lua_pushboolean(L, sun_params.sunrise_visible);
1998         lua_setfield(L, -2, "sunrise_visible");
1999         lua_pushnumber(L, sun_params.scale);
2000         lua_setfield(L, -2, "scale");
2001         return 1;
2002 }
2003
2004 // set_moon(self, moon_parameters)
2005 int ObjectRef::l_set_moon(lua_State *L)
2006 {
2007         NO_MAP_LOCK_REQUIRED;
2008         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2009         RemotePlayer *player = getplayer(ref);
2010         if (player == nullptr)
2011                 return 0;
2012
2013         MoonParams moon_params = player->getMoonParams();
2014
2015         // reset if empty
2016         if (lua_isnoneornil(L, 2)) {
2017                 moon_params = SkyboxDefaults::getMoonDefaults();
2018         } else {
2019                 luaL_checktype(L, 2, LUA_TTABLE);
2020                 moon_params.visible = getboolfield_default(L, 2,   "visible", moon_params.visible);
2021                 moon_params.texture = getstringfield_default(L, 2, "texture", moon_params.texture);
2022                 moon_params.tonemap = getstringfield_default(L, 2, "tonemap", moon_params.tonemap);
2023                 moon_params.scale   = getfloatfield_default(L, 2,  "scale",   moon_params.scale);
2024         }
2025
2026         getServer(L)->setMoon(player, moon_params);
2027         return 0;
2028 }
2029
2030 // get_moon(self)
2031 int ObjectRef::l_get_moon(lua_State *L)
2032 {
2033         NO_MAP_LOCK_REQUIRED;
2034         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2035         RemotePlayer *player = getplayer(ref);
2036         if (player == nullptr)
2037                 return 0;
2038
2039         const MoonParams &moon_params = player->getMoonParams();
2040
2041         lua_newtable(L);
2042         lua_pushboolean(L, moon_params.visible);
2043         lua_setfield(L, -2, "visible");
2044         lua_pushstring(L, moon_params.texture.c_str());
2045         lua_setfield(L, -2, "texture");
2046         lua_pushstring(L, moon_params.tonemap.c_str());
2047         lua_setfield(L, -2, "tonemap");
2048         lua_pushnumber(L, moon_params.scale);
2049         lua_setfield(L, -2, "scale");
2050         return 1;
2051 }
2052
2053 // set_stars(self, star_parameters)
2054 int ObjectRef::l_set_stars(lua_State *L)
2055 {
2056         NO_MAP_LOCK_REQUIRED;
2057         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2058         RemotePlayer *player = getplayer(ref);
2059         if (player == nullptr)
2060                 return 0;
2061
2062         StarParams star_params = player->getStarParams();
2063
2064         // reset if empty
2065         if (lua_isnoneornil(L, 2)) {
2066                 star_params = SkyboxDefaults::getStarDefaults();
2067         } else {
2068                 luaL_checktype(L, 2, LUA_TTABLE);
2069                 star_params.visible = getboolfield_default(L, 2, "visible", star_params.visible);
2070                 star_params.count   = getintfield_default(L, 2,  "count",   star_params.count);
2071
2072                 lua_getfield(L, 2, "star_color");
2073                 if (!lua_isnil(L, -1))
2074                         read_color(L, -1, &star_params.starcolor);
2075                 lua_pop(L, 1);
2076
2077                 star_params.scale = getfloatfield_default(L, 2,
2078                         "scale", star_params.scale);
2079                 star_params.day_opacity = getfloatfield_default(L, 2,
2080                         "day_opacity", star_params.day_opacity);
2081         }
2082
2083         getServer(L)->setStars(player, star_params);
2084         return 0;
2085 }
2086
2087 // get_stars(self)
2088 int ObjectRef::l_get_stars(lua_State *L)
2089 {
2090         NO_MAP_LOCK_REQUIRED;
2091         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2092         RemotePlayer *player = getplayer(ref);
2093         if (player == nullptr)
2094                 return 0;
2095
2096         const StarParams &star_params = player->getStarParams();
2097
2098         lua_newtable(L);
2099         lua_pushboolean(L, star_params.visible);
2100         lua_setfield(L, -2, "visible");
2101         lua_pushnumber(L, star_params.count);
2102         lua_setfield(L, -2, "count");
2103         push_ARGB8(L, star_params.starcolor);
2104         lua_setfield(L, -2, "star_color");
2105         lua_pushnumber(L, star_params.scale);
2106         lua_setfield(L, -2, "scale");
2107         lua_pushnumber(L, star_params.day_opacity);
2108         lua_setfield(L, -2, "day_opacity");
2109         return 1;
2110 }
2111
2112 // set_clouds(self, cloud_parameters)
2113 int ObjectRef::l_set_clouds(lua_State *L)
2114 {
2115         NO_MAP_LOCK_REQUIRED;
2116         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2117         RemotePlayer *player = getplayer(ref);
2118         if (player == nullptr)
2119                 return 0;
2120
2121         CloudParams cloud_params = player->getCloudParams();
2122
2123         // reset if empty
2124         if (lua_isnoneornil(L, 2)) {
2125                 cloud_params = SkyboxDefaults::getCloudDefaults();
2126         } else {
2127                 luaL_checktype(L, 2, LUA_TTABLE);
2128                 cloud_params.density = getfloatfield_default(L, 2, "density", cloud_params.density);
2129
2130                 lua_getfield(L, 2, "color");
2131                 if (!lua_isnil(L, -1))
2132                         read_color(L, -1, &cloud_params.color_bright);
2133                 lua_pop(L, 1);
2134                 lua_getfield(L, 2, "ambient");
2135                 if (!lua_isnil(L, -1))
2136                         read_color(L, -1, &cloud_params.color_ambient);
2137                 lua_pop(L, 1);
2138
2139                 cloud_params.height    = getfloatfield_default(L, 2, "height",    cloud_params.height);
2140                 cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness);
2141
2142                 lua_getfield(L, 2, "speed");
2143                 if (lua_istable(L, -1)) {
2144                         v2f new_speed;
2145                         new_speed.X = getfloatfield_default(L, -1, "x", 0);
2146                         new_speed.Y = getfloatfield_default(L, -1, "z", 0);
2147                         cloud_params.speed = new_speed;
2148                 }
2149                 lua_pop(L, 1);
2150         }
2151
2152         getServer(L)->setClouds(player, cloud_params);
2153         return 0;
2154 }
2155
2156 int ObjectRef::l_get_clouds(lua_State *L)
2157 {
2158         NO_MAP_LOCK_REQUIRED;
2159         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2160         RemotePlayer *player = getplayer(ref);
2161         if (player == nullptr)
2162                 return 0;
2163
2164         const CloudParams &cloud_params = player->getCloudParams();
2165
2166         lua_newtable(L);
2167         lua_pushnumber(L, cloud_params.density);
2168         lua_setfield(L, -2, "density");
2169         push_ARGB8(L, cloud_params.color_bright);
2170         lua_setfield(L, -2, "color");
2171         push_ARGB8(L, cloud_params.color_ambient);
2172         lua_setfield(L, -2, "ambient");
2173         lua_pushnumber(L, cloud_params.height);
2174         lua_setfield(L, -2, "height");
2175         lua_pushnumber(L, cloud_params.thickness);
2176         lua_setfield(L, -2, "thickness");
2177         lua_newtable(L);
2178         lua_pushnumber(L, cloud_params.speed.X);
2179         lua_setfield(L, -2, "x");
2180         lua_pushnumber(L, cloud_params.speed.Y);
2181         lua_setfield(L, -2, "y");
2182         lua_setfield(L, -2, "speed");
2183         return 1;
2184 }
2185
2186
2187 // override_day_night_ratio(self, ratio)
2188 int ObjectRef::l_override_day_night_ratio(lua_State *L)
2189 {
2190         NO_MAP_LOCK_REQUIRED;
2191         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2192         RemotePlayer *player = getplayer(ref);
2193         if (player == nullptr)
2194                 return 0;
2195
2196         bool do_override = false;
2197         float ratio = 0.0f;
2198
2199         if (!lua_isnil(L, 2)) {
2200                 do_override = true;
2201                 ratio = readParam<float>(L, 2);
2202                 luaL_argcheck(L, ratio >= 0.0f && ratio <= 1.0f, 1,
2203                         "value must be between 0 and 1");
2204         }
2205
2206         getServer(L)->overrideDayNightRatio(player, do_override, ratio);
2207         return 0;
2208 }
2209
2210 // get_day_night_ratio(self)
2211 int ObjectRef::l_get_day_night_ratio(lua_State *L)
2212 {
2213         NO_MAP_LOCK_REQUIRED;
2214         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2215         RemotePlayer *player = getplayer(ref);
2216         if (player == nullptr)
2217                 return 0;
2218
2219         bool do_override;
2220         float ratio;
2221         player->getDayNightRatio(&do_override, &ratio);
2222
2223         if (do_override)
2224                 lua_pushnumber(L, ratio);
2225         else
2226                 lua_pushnil(L);
2227
2228         return 1;
2229 }
2230
2231 // set_minimap_modes(self, modes, selected_mode)
2232 int ObjectRef::l_set_minimap_modes(lua_State *L)
2233 {
2234         NO_MAP_LOCK_REQUIRED;
2235         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2236         RemotePlayer *player = getplayer(ref);
2237         if (player == nullptr)
2238                 return 0;
2239
2240         luaL_checktype(L, 2, LUA_TTABLE);
2241         std::vector<MinimapMode> modes;
2242         s16 selected_mode = readParam<s16>(L, 3);
2243
2244         lua_pushnil(L);
2245         while (lua_next(L, 2) != 0) {
2246                 /* key is at index -2, value is at index -1 */
2247                 if (lua_istable(L, -1)) {
2248                         bool ok = true;
2249                         MinimapMode mode;
2250                         std::string type = getstringfield_default(L, -1, "type", "");
2251                         if (type == "off")
2252                                 mode.type = MINIMAP_TYPE_OFF;
2253                         else if (type == "surface")
2254                                 mode.type = MINIMAP_TYPE_SURFACE;
2255                         else if (type == "radar")
2256                                 mode.type = MINIMAP_TYPE_RADAR;
2257                         else if (type == "texture") {
2258                                 mode.type = MINIMAP_TYPE_TEXTURE;
2259                                 mode.texture = getstringfield_default(L, -1, "texture", "");
2260                                 mode.scale = getintfield_default(L, -1, "scale", 1);
2261                         } else {
2262                                 warningstream << "Minimap mode of unknown type \"" << type.c_str()
2263                                         << "\" ignored.\n" << std::endl;
2264                                 ok = false;
2265                         }
2266
2267                         if (ok) {
2268                                 mode.label = getstringfield_default(L, -1, "label", "");
2269                                 // Size is limited to 512. Performance gets poor if size too large, and
2270                                 // segfaults have been experienced.
2271                                 mode.size = rangelim(getintfield_default(L, -1, "size", 0), 1, 512);
2272                                 modes.push_back(mode);
2273                         }
2274                 }
2275                 /* removes 'value'; keeps 'key' for next iteration */
2276                 lua_pop(L, 1);
2277         }
2278         lua_pop(L, 1); // Remove key
2279
2280         getServer(L)->SendMinimapModes(player->getPeerId(), modes, selected_mode);
2281         return 0;
2282 }
2283
2284 // set_lighting(self, lighting)
2285 int ObjectRef::l_set_lighting(lua_State *L)
2286 {
2287         NO_MAP_LOCK_REQUIRED;
2288         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2289         RemotePlayer *player = getplayer(ref);
2290         if (player == nullptr)
2291                 return 0;
2292
2293         luaL_checktype(L, 2, LUA_TTABLE);
2294         Lighting lighting = player->getLighting();
2295         lua_getfield(L, 2, "shadows");
2296         if (lua_istable(L, -1)) {
2297                 lighting.shadow_intensity = getfloatfield_default(L, -1, "intensity", lighting.shadow_intensity);
2298         }
2299         lighting.saturation = getfloatfield_default(L, 2, "saturation", lighting.saturation);
2300         lua_pop(L, -1);
2301
2302         getServer(L)->setLighting(player, lighting);
2303         return 0;
2304 }
2305
2306 // get_lighting(self)
2307 int ObjectRef::l_get_lighting(lua_State *L)
2308 {
2309         NO_MAP_LOCK_REQUIRED;
2310         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2311         RemotePlayer *player = getplayer(ref);
2312         if (player == nullptr)
2313                 return 0;
2314
2315         const Lighting &lighting = player->getLighting();
2316
2317         lua_newtable(L); // result
2318         lua_newtable(L); // "shadows"
2319         lua_pushnumber(L, lighting.shadow_intensity);
2320         lua_setfield(L, -2, "intensity");
2321         lua_setfield(L, -2, "shadows");
2322         lua_pushnumber(L, lighting.saturation);
2323         lua_setfield(L, -2, "saturation");
2324         return 1;
2325 }
2326
2327 // respawn(self)
2328 int ObjectRef::l_respawn(lua_State *L)
2329 {
2330         NO_MAP_LOCK_REQUIRED;
2331         ObjectRef *ref = checkObject<ObjectRef>(L, 1);
2332         RemotePlayer *player = getplayer(ref);
2333         if (player == nullptr)
2334                 return 0;
2335
2336         getServer(L)->RespawnPlayer(player->getPeerId());
2337         lua_pushboolean(L, true);
2338         return 1;
2339 }
2340
2341
2342 ObjectRef::ObjectRef(ServerActiveObject *object):
2343         m_object(object)
2344 {}
2345
2346 // Creates an ObjectRef and leaves it on top of stack
2347 // Not callable from Lua; all references are created on the C side.
2348 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
2349 {
2350         ObjectRef *obj = new ObjectRef(object);
2351         *(void **)(lua_newuserdata(L, sizeof(void *))) = obj;
2352         luaL_getmetatable(L, className);
2353         lua_setmetatable(L, -2);
2354 }
2355
2356 void ObjectRef::set_null(lua_State *L)
2357 {
2358         ObjectRef *obj = checkObject<ObjectRef>(L, -1);
2359         obj->m_object = nullptr;
2360 }
2361
2362 void ObjectRef::Register(lua_State *L)
2363 {
2364         static const luaL_Reg metamethods[] = {
2365                 {"__gc", gc_object},
2366                 {0, 0}
2367         };
2368         registerClass(L, className, methods, metamethods);
2369 }
2370
2371 const char ObjectRef::className[] = "ObjectRef";
2372 luaL_Reg ObjectRef::methods[] = {
2373         // ServerActiveObject
2374         luamethod(ObjectRef, remove),
2375         luamethod_aliased(ObjectRef, get_pos, getpos),
2376         luamethod_aliased(ObjectRef, set_pos, setpos),
2377         luamethod_aliased(ObjectRef, move_to, moveto),
2378         luamethod(ObjectRef, punch),
2379         luamethod(ObjectRef, right_click),
2380         luamethod(ObjectRef, set_hp),
2381         luamethod(ObjectRef, get_hp),
2382         luamethod(ObjectRef, get_inventory),
2383         luamethod(ObjectRef, get_wield_list),
2384         luamethod(ObjectRef, get_wield_index),
2385         luamethod(ObjectRef, get_wielded_item),
2386         luamethod(ObjectRef, set_wielded_item),
2387         luamethod(ObjectRef, set_armor_groups),
2388         luamethod(ObjectRef, get_armor_groups),
2389         luamethod(ObjectRef, set_animation),
2390         luamethod(ObjectRef, get_animation),
2391         luamethod(ObjectRef, set_animation_frame_speed),
2392         luamethod(ObjectRef, set_bone_position),
2393         luamethod(ObjectRef, get_bone_position),
2394         luamethod(ObjectRef, set_attach),
2395         luamethod(ObjectRef, get_attach),
2396         luamethod(ObjectRef, get_children),
2397         luamethod(ObjectRef, set_detach),
2398         luamethod(ObjectRef, set_properties),
2399         luamethod(ObjectRef, get_properties),
2400         luamethod(ObjectRef, set_nametag_attributes),
2401         luamethod(ObjectRef, get_nametag_attributes),
2402
2403         luamethod_aliased(ObjectRef, set_velocity, setvelocity),
2404         luamethod_aliased(ObjectRef, add_velocity, add_player_velocity),
2405         luamethod_aliased(ObjectRef, get_velocity, getvelocity),
2406         luamethod_dep(ObjectRef, get_velocity, get_player_velocity),
2407
2408         // LuaEntitySAO-only
2409         luamethod_aliased(ObjectRef, set_acceleration, setacceleration),
2410         luamethod_aliased(ObjectRef, get_acceleration, getacceleration),
2411         luamethod_aliased(ObjectRef, set_yaw, setyaw),
2412         luamethod_aliased(ObjectRef, get_yaw, getyaw),
2413         luamethod(ObjectRef, set_rotation),
2414         luamethod(ObjectRef, get_rotation),
2415         luamethod_aliased(ObjectRef, set_texture_mod, settexturemod),
2416         luamethod(ObjectRef, get_texture_mod),
2417         luamethod_aliased(ObjectRef, set_sprite, setsprite),
2418         luamethod(ObjectRef, get_entity_name),
2419         luamethod(ObjectRef, get_luaentity),
2420
2421         // Player-only
2422         luamethod(ObjectRef, is_player),
2423         luamethod(ObjectRef, get_player_name),
2424         luamethod(ObjectRef, get_look_dir),
2425         luamethod(ObjectRef, get_look_pitch),
2426         luamethod(ObjectRef, get_look_yaw),
2427         luamethod(ObjectRef, get_look_vertical),
2428         luamethod(ObjectRef, get_look_horizontal),
2429         luamethod(ObjectRef, set_look_horizontal),
2430         luamethod(ObjectRef, set_look_vertical),
2431         luamethod(ObjectRef, set_look_yaw),
2432         luamethod(ObjectRef, set_look_pitch),
2433         luamethod(ObjectRef, get_fov),
2434         luamethod(ObjectRef, set_fov),
2435         luamethod(ObjectRef, get_breath),
2436         luamethod(ObjectRef, set_breath),
2437         luamethod(ObjectRef, get_attribute),
2438         luamethod(ObjectRef, set_attribute),
2439         luamethod(ObjectRef, get_meta),
2440         luamethod(ObjectRef, set_inventory_formspec),
2441         luamethod(ObjectRef, get_inventory_formspec),
2442         luamethod(ObjectRef, set_formspec_prepend),
2443         luamethod(ObjectRef, get_formspec_prepend),
2444         luamethod(ObjectRef, get_player_control),
2445         luamethod(ObjectRef, get_player_control_bits),
2446         luamethod(ObjectRef, set_physics_override),
2447         luamethod(ObjectRef, get_physics_override),
2448         luamethod(ObjectRef, hud_add),
2449         luamethod(ObjectRef, hud_remove),
2450         luamethod(ObjectRef, hud_change),
2451         luamethod(ObjectRef, hud_get),
2452         luamethod(ObjectRef, hud_set_flags),
2453         luamethod(ObjectRef, hud_get_flags),
2454         luamethod(ObjectRef, hud_set_hotbar_itemcount),
2455         luamethod(ObjectRef, hud_get_hotbar_itemcount),
2456         luamethod(ObjectRef, hud_set_hotbar_image),
2457         luamethod(ObjectRef, hud_get_hotbar_image),
2458         luamethod(ObjectRef, hud_set_hotbar_selected_image),
2459         luamethod(ObjectRef, hud_get_hotbar_selected_image),
2460         luamethod(ObjectRef, set_sky),
2461         luamethod(ObjectRef, get_sky),
2462         luamethod(ObjectRef, get_sky_color),
2463         luamethod(ObjectRef, set_sun),
2464         luamethod(ObjectRef, get_sun),
2465         luamethod(ObjectRef, set_moon),
2466         luamethod(ObjectRef, get_moon),
2467         luamethod(ObjectRef, set_stars),
2468         luamethod(ObjectRef, get_stars),
2469         luamethod(ObjectRef, set_clouds),
2470         luamethod(ObjectRef, get_clouds),
2471         luamethod(ObjectRef, override_day_night_ratio),
2472         luamethod(ObjectRef, get_day_night_ratio),
2473         luamethod(ObjectRef, set_local_animation),
2474         luamethod(ObjectRef, get_local_animation),
2475         luamethod(ObjectRef, set_eye_offset),
2476         luamethod(ObjectRef, get_eye_offset),
2477         luamethod(ObjectRef, send_mapblock),
2478         luamethod(ObjectRef, set_minimap_modes),
2479         luamethod(ObjectRef, set_lighting),
2480         luamethod(ObjectRef, get_lighting),
2481         luamethod(ObjectRef, respawn),
2482
2483         {0,0}
2484 };