]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_object.cpp
7ff1f58bc21f569fb3ca0051bf57b2e4909e1a06
[dragonfireclient.git] / src / script / lua_api / l_object.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "lua_api/l_object.h"
21 #include <cmath>
22 #include "lua_api/l_internal.h"
23 #include "lua_api/l_inventory.h"
24 #include "lua_api/l_item.h"
25 #include "lua_api/l_playermeta.h"
26 #include "common/c_converter.h"
27 #include "common/c_content.h"
28 #include "log.h"
29 #include "tool.h"
30 #include "serverobject.h"
31 #include "content_sao.h"
32 #include "remoteplayer.h"
33 #include "server.h"
34 #include "hud.h"
35 #include "scripting_server.h"
36
37 /*
38         ObjectRef
39 */
40
41
42 ObjectRef* ObjectRef::checkobject(lua_State *L, int narg)
43 {
44         luaL_checktype(L, narg, LUA_TUSERDATA);
45         void *ud = luaL_checkudata(L, narg, className);
46         if (!ud) luaL_typerror(L, narg, className);
47         return *(ObjectRef**)ud;  // unbox pointer
48 }
49
50 ServerActiveObject* ObjectRef::getobject(ObjectRef *ref)
51 {
52         ServerActiveObject *co = ref->m_object;
53         return co;
54 }
55
56 LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
57 {
58         ServerActiveObject *obj = getobject(ref);
59         if (obj == NULL)
60                 return NULL;
61         if (obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
62                 return NULL;
63         return (LuaEntitySAO*)obj;
64 }
65
66 PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
67 {
68         ServerActiveObject *obj = getobject(ref);
69         if (obj == NULL)
70                 return NULL;
71         if (obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
72                 return NULL;
73         return (PlayerSAO*)obj;
74 }
75
76 RemotePlayer *ObjectRef::getplayer(ObjectRef *ref)
77 {
78         PlayerSAO *playersao = getplayersao(ref);
79         if (playersao == NULL)
80                 return NULL;
81         return playersao->getPlayer();
82 }
83
84 // Exported functions
85
86 // garbage collector
87 int ObjectRef::gc_object(lua_State *L) {
88         ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
89         //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
90         delete o;
91         return 0;
92 }
93
94 // remove(self)
95 int ObjectRef::l_remove(lua_State *L)
96 {
97         GET_ENV_PTR;
98
99         ObjectRef *ref = checkobject(L, 1);
100         ServerActiveObject *co = getobject(ref);
101         if (co == NULL)
102                 return 0;
103         if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
104                 return 0;
105
106         co->clearChildAttachments();
107         co->clearParentAttachment();
108
109         verbosestream << "ObjectRef::l_remove(): id=" << co->getId() << std::endl;
110         co->m_pending_removal = true;
111         return 0;
112 }
113
114 // get_pos(self)
115 // returns: {x=num, y=num, z=num}
116 int ObjectRef::l_get_pos(lua_State *L)
117 {
118         NO_MAP_LOCK_REQUIRED;
119         ObjectRef *ref = checkobject(L, 1);
120         ServerActiveObject *co = getobject(ref);
121         if (co == NULL) return 0;
122         v3f pos = co->getBasePosition() / BS;
123         lua_newtable(L);
124         lua_pushnumber(L, pos.X);
125         lua_setfield(L, -2, "x");
126         lua_pushnumber(L, pos.Y);
127         lua_setfield(L, -2, "y");
128         lua_pushnumber(L, pos.Z);
129         lua_setfield(L, -2, "z");
130         return 1;
131 }
132
133 // set_pos(self, pos)
134 int ObjectRef::l_set_pos(lua_State *L)
135 {
136         NO_MAP_LOCK_REQUIRED;
137         ObjectRef *ref = checkobject(L, 1);
138         //LuaEntitySAO *co = getluaobject(ref);
139         ServerActiveObject *co = getobject(ref);
140         if (co == NULL) return 0;
141         // pos
142         v3f pos = checkFloatPos(L, 2);
143         // Do it
144         co->setPos(pos);
145         return 0;
146 }
147
148 // move_to(self, pos, continuous=false)
149 int ObjectRef::l_move_to(lua_State *L)
150 {
151         NO_MAP_LOCK_REQUIRED;
152         ObjectRef *ref = checkobject(L, 1);
153         //LuaEntitySAO *co = getluaobject(ref);
154         ServerActiveObject *co = getobject(ref);
155         if (co == NULL) return 0;
156         // pos
157         v3f pos = checkFloatPos(L, 2);
158         // continuous
159         bool continuous = readParam<bool>(L, 3);
160         // Do it
161         co->moveTo(pos, continuous);
162         return 0;
163 }
164
165 // punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
166 int ObjectRef::l_punch(lua_State *L)
167 {
168         NO_MAP_LOCK_REQUIRED;
169         ObjectRef *ref = checkobject(L, 1);
170         ObjectRef *puncher_ref = checkobject(L, 2);
171         ServerActiveObject *co = getobject(ref);
172         ServerActiveObject *puncher = getobject(puncher_ref);
173         if (!co || !puncher)
174                 return 0;
175         v3f dir;
176         if (lua_type(L, 5) != LUA_TTABLE)
177                 dir = co->getBasePosition() - puncher->getBasePosition();
178         else
179                 dir = read_v3f(L, 5);
180         float time_from_last_punch = 1000000;
181         if (lua_isnumber(L, 3))
182                 time_from_last_punch = lua_tonumber(L, 3);
183         ToolCapabilities toolcap = read_tool_capabilities(L, 4);
184         dir.normalize();
185
186         u16 src_original_hp = co->getHP();
187         u16 dst_origin_hp = puncher->getHP();
188
189         // Do it
190         co->punch(dir, &toolcap, puncher, time_from_last_punch);
191
192         // If the punched is a player, and its HP changed
193         if (src_original_hp != co->getHP() &&
194                         co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
195                 getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co,
196                                 PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher));
197         }
198
199         // If the puncher is a player, and its HP changed
200         if (dst_origin_hp != puncher->getHP() &&
201                         puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
202                 getServer(L)->SendPlayerHPOrDie((PlayerSAO *)puncher,
203                                 PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, co));
204         }
205         return 0;
206 }
207
208 // right_click(self, clicker); clicker = an another ObjectRef
209 int ObjectRef::l_right_click(lua_State *L)
210 {
211         NO_MAP_LOCK_REQUIRED;
212         ObjectRef *ref = checkobject(L, 1);
213         ObjectRef *ref2 = checkobject(L, 2);
214         ServerActiveObject *co = getobject(ref);
215         ServerActiveObject *co2 = getobject(ref2);
216         if (co == NULL) return 0;
217         if (co2 == NULL) return 0;
218         // Do it
219         co->rightClick(co2);
220         return 0;
221 }
222
223 // set_hp(self, hp)
224 // hp = number of hitpoints (2 * number of hearts)
225 // returns: nil
226 int ObjectRef::l_set_hp(lua_State *L)
227 {
228         NO_MAP_LOCK_REQUIRED;
229
230         // Get Object
231         ObjectRef *ref = checkobject(L, 1);
232         luaL_checknumber(L, 2);
233         ServerActiveObject *co = getobject(ref);
234         if (co == NULL)
235                 return 0;
236
237         // Get HP
238         int hp = lua_tonumber(L, 2);
239
240         // Get Reason
241         PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP);
242         reason.from_mod = true;
243         if (lua_istable(L, 3)) {
244                 lua_pushvalue(L, 3);
245
246                 lua_getfield(L, -1, "type");
247                 if (lua_isstring(L, -1) &&
248                                 !reason.setTypeFromString(readParam<std::string>(L, -1))) {
249                         errorstream << "Bad type given!" << std::endl;
250                 }
251                 lua_pop(L, 1);
252
253                 reason.lua_reference = luaL_ref(L, LUA_REGISTRYINDEX);
254         }
255
256         // Do it
257         co->setHP(hp, reason);
258         if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
259                 getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, reason);
260
261         if (reason.hasLuaReference())
262                 luaL_unref(L, LUA_REGISTRYINDEX, reason.lua_reference);
263
264         // Return
265         return 0;
266 }
267
268 // get_hp(self)
269 // returns: number of hitpoints (2 * number of hearts)
270 // 0 if not applicable to this type of object
271 int ObjectRef::l_get_hp(lua_State *L)
272 {
273         NO_MAP_LOCK_REQUIRED;
274         ObjectRef *ref = checkobject(L, 1);
275         ServerActiveObject *co = getobject(ref);
276         if (co == NULL) {
277                 // Default hp is 1
278                 lua_pushnumber(L, 1);
279                 return 1;
280         }
281         int hp = co->getHP();
282         /*infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
283                         <<" hp="<<hp<<std::endl;*/
284         // Return
285         lua_pushnumber(L, hp);
286         return 1;
287 }
288
289 // get_inventory(self)
290 int ObjectRef::l_get_inventory(lua_State *L)
291 {
292         NO_MAP_LOCK_REQUIRED;
293         ObjectRef *ref = checkobject(L, 1);
294         ServerActiveObject *co = getobject(ref);
295         if (co == NULL) return 0;
296         // Do it
297         InventoryLocation loc = co->getInventoryLocation();
298         if (getServer(L)->getInventory(loc) != NULL)
299                 InvRef::create(L, loc);
300         else
301                 lua_pushnil(L); // An object may have no inventory (nil)
302         return 1;
303 }
304
305 // get_wield_list(self)
306 int ObjectRef::l_get_wield_list(lua_State *L)
307 {
308         NO_MAP_LOCK_REQUIRED;
309         ObjectRef *ref = checkobject(L, 1);
310         ServerActiveObject *co = getobject(ref);
311         if (co == NULL) return 0;
312         // Do it
313         lua_pushstring(L, co->getWieldList().c_str());
314         return 1;
315 }
316
317 // get_wield_index(self)
318 int ObjectRef::l_get_wield_index(lua_State *L)
319 {
320         NO_MAP_LOCK_REQUIRED;
321         ObjectRef *ref = checkobject(L, 1);
322         ServerActiveObject *co = getobject(ref);
323         if (co == NULL) return 0;
324         // Do it
325         lua_pushinteger(L, co->getWieldIndex() + 1);
326         return 1;
327 }
328
329 // get_wielded_item(self)
330 int ObjectRef::l_get_wielded_item(lua_State *L)
331 {
332         NO_MAP_LOCK_REQUIRED;
333         ObjectRef *ref = checkobject(L, 1);
334         ServerActiveObject *co = getobject(ref);
335         if (co == NULL) {
336                 // Empty ItemStack
337                 LuaItemStack::create(L, ItemStack());
338                 return 1;
339         }
340         // Do it
341         LuaItemStack::create(L, co->getWieldedItem());
342         return 1;
343 }
344
345 // set_wielded_item(self, itemstack or itemstring or table or nil)
346 int ObjectRef::l_set_wielded_item(lua_State *L)
347 {
348         NO_MAP_LOCK_REQUIRED;
349         ObjectRef *ref = checkobject(L, 1);
350         ServerActiveObject *co = getobject(ref);
351         if (co == NULL) return 0;
352         // Do it
353         ItemStack item = read_item(L, 2, getServer(L)->idef());
354         bool success = co->setWieldedItem(item);
355         if (success && co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
356                 getServer(L)->SendInventory(((PlayerSAO*)co));
357         }
358         lua_pushboolean(L, success);
359         return 1;
360 }
361
362 // set_armor_groups(self, groups)
363 int ObjectRef::l_set_armor_groups(lua_State *L)
364 {
365         NO_MAP_LOCK_REQUIRED;
366         ObjectRef *ref = checkobject(L, 1);
367         ServerActiveObject *co = getobject(ref);
368         if (co == NULL) return 0;
369         // Do it
370         ItemGroupList groups;
371         read_groups(L, 2, groups);
372         co->setArmorGroups(groups);
373         return 0;
374 }
375
376 // get_armor_groups(self)
377 int ObjectRef::l_get_armor_groups(lua_State *L)
378 {
379         NO_MAP_LOCK_REQUIRED;
380         ObjectRef *ref = checkobject(L, 1);
381         ServerActiveObject *co = getobject(ref);
382         if (co == NULL)
383                 return 0;
384         // Do it
385         push_groups(L, co->getArmorGroups());
386         return 1;
387 }
388
389 // set_physics_override(self, physics_override_speed, physics_override_jump,
390 //                      physics_override_gravity, sneak, sneak_glitch, new_move)
391 int ObjectRef::l_set_physics_override(lua_State *L)
392 {
393         NO_MAP_LOCK_REQUIRED;
394         ObjectRef *ref = checkobject(L, 1);
395         PlayerSAO *co = (PlayerSAO *) getobject(ref);
396         if (co == NULL) return 0;
397         // Do it
398         if (lua_istable(L, 2)) {
399                 co->m_physics_override_speed = getfloatfield_default(
400                                 L, 2, "speed", co->m_physics_override_speed);
401                 co->m_physics_override_jump = getfloatfield_default(
402                                 L, 2, "jump", co->m_physics_override_jump);
403                 co->m_physics_override_gravity = getfloatfield_default(
404                                 L, 2, "gravity", co->m_physics_override_gravity);
405                 co->m_physics_override_sneak = getboolfield_default(
406                                 L, 2, "sneak", co->m_physics_override_sneak);
407                 co->m_physics_override_sneak_glitch = getboolfield_default(
408                                 L, 2, "sneak_glitch", co->m_physics_override_sneak_glitch);
409                 co->m_physics_override_new_move = getboolfield_default(
410                                 L, 2, "new_move", co->m_physics_override_new_move);
411                 co->m_physics_override_sent = false;
412         } else {
413                 // old, non-table format
414                 if (!lua_isnil(L, 2)) {
415                         co->m_physics_override_speed = lua_tonumber(L, 2);
416                         co->m_physics_override_sent = false;
417                 }
418                 if (!lua_isnil(L, 3)) {
419                         co->m_physics_override_jump = lua_tonumber(L, 3);
420                         co->m_physics_override_sent = false;
421                 }
422                 if (!lua_isnil(L, 4)) {
423                         co->m_physics_override_gravity = lua_tonumber(L, 4);
424                         co->m_physics_override_sent = false;
425                 }
426         }
427         return 0;
428 }
429
430 // get_physics_override(self)
431 int ObjectRef::l_get_physics_override(lua_State *L)
432 {
433         NO_MAP_LOCK_REQUIRED;
434         ObjectRef *ref = checkobject(L, 1);
435         PlayerSAO *co = (PlayerSAO *)getobject(ref);
436         if (co == NULL)
437                 return 0;
438         // Do it
439         lua_newtable(L);
440         lua_pushnumber(L, co->m_physics_override_speed);
441         lua_setfield(L, -2, "speed");
442         lua_pushnumber(L, co->m_physics_override_jump);
443         lua_setfield(L, -2, "jump");
444         lua_pushnumber(L, co->m_physics_override_gravity);
445         lua_setfield(L, -2, "gravity");
446         lua_pushboolean(L, co->m_physics_override_sneak);
447         lua_setfield(L, -2, "sneak");
448         lua_pushboolean(L, co->m_physics_override_sneak_glitch);
449         lua_setfield(L, -2, "sneak_glitch");
450         lua_pushboolean(L, co->m_physics_override_new_move);
451         lua_setfield(L, -2, "new_move");
452         return 1;
453 }
454
455 // set_animation(self, frame_range, frame_speed, frame_blend, frame_loop)
456 int ObjectRef::l_set_animation(lua_State *L)
457 {
458         NO_MAP_LOCK_REQUIRED;
459         ObjectRef *ref = checkobject(L, 1);
460         ServerActiveObject *co = getobject(ref);
461         if (co == NULL) return 0;
462         // Do it
463         v2f frames = v2f(1, 1);
464         if (!lua_isnil(L, 2))
465                 frames = readParam<v2f>(L, 2);
466         float frame_speed = 15;
467         if (!lua_isnil(L, 3))
468                 frame_speed = lua_tonumber(L, 3);
469         float frame_blend = 0;
470         if (!lua_isnil(L, 4))
471                 frame_blend = lua_tonumber(L, 4);
472         bool frame_loop = true;
473         if (lua_isboolean(L, 5))
474                 frame_loop = readParam<bool>(L, 5);
475         co->setAnimation(frames, frame_speed, frame_blend, frame_loop);
476         return 0;
477 }
478
479 // get_animation(self)
480 int ObjectRef::l_get_animation(lua_State *L)
481 {
482         NO_MAP_LOCK_REQUIRED;
483         ObjectRef *ref = checkobject(L, 1);
484         ServerActiveObject *co = getobject(ref);
485         if (co == NULL)
486                 return 0;
487         // Do it
488         v2f frames = v2f(1,1);
489         float frame_speed = 15;
490         float frame_blend = 0;
491         bool frame_loop = true;
492         co->getAnimation(&frames, &frame_speed, &frame_blend, &frame_loop);
493
494         push_v2f(L, frames);
495         lua_pushnumber(L, frame_speed);
496         lua_pushnumber(L, frame_blend);
497         lua_pushboolean(L, frame_loop);
498         return 4;
499 }
500
501 // set_local_animation(self, {stand/idle}, {walk}, {dig}, {walk+dig}, frame_speed)
502 int ObjectRef::l_set_local_animation(lua_State *L)
503 {
504         NO_MAP_LOCK_REQUIRED;
505         ObjectRef *ref = checkobject(L, 1);
506         RemotePlayer *player = getplayer(ref);
507         if (player == NULL)
508                 return 0;
509         // Do it
510         v2s32 frames[4];
511         for (int i=0;i<4;i++) {
512                 if (!lua_isnil(L, 2+1))
513                         frames[i] = read_v2s32(L, 2+i);
514         }
515         float frame_speed = 30;
516         if (!lua_isnil(L, 6))
517                 frame_speed = lua_tonumber(L, 6);
518
519         getServer(L)->setLocalPlayerAnimations(player, frames, frame_speed);
520         lua_pushboolean(L, true);
521         return 1;
522 }
523
524 // get_local_animation(self)
525 int ObjectRef::l_get_local_animation(lua_State *L)
526 {
527         NO_MAP_LOCK_REQUIRED
528         ObjectRef *ref = checkobject(L, 1);
529         RemotePlayer *player = getplayer(ref);
530         if (player == NULL)
531                 return 0;
532
533         v2s32 frames[4];
534         float frame_speed;
535         player->getLocalAnimations(frames, &frame_speed);
536
537         for (const v2s32 &frame : frames) {
538                 push_v2s32(L, frame);
539         }
540
541         lua_pushnumber(L, frame_speed);
542         return 5;
543 }
544
545 // set_eye_offset(self, v3f first pv, v3f third pv)
546 int ObjectRef::l_set_eye_offset(lua_State *L)
547 {
548         NO_MAP_LOCK_REQUIRED;
549         ObjectRef *ref = checkobject(L, 1);
550         RemotePlayer *player = getplayer(ref);
551         if (player == NULL)
552                 return 0;
553         // Do it
554         v3f offset_first = v3f(0, 0, 0);
555         v3f offset_third = v3f(0, 0, 0);
556
557         if (!lua_isnil(L, 2))
558                 offset_first = read_v3f(L, 2);
559         if (!lua_isnil(L, 3))
560                 offset_third = read_v3f(L, 3);
561
562         // Prevent abuse of offset values (keep player always visible)
563         offset_third.X = rangelim(offset_third.X,-10,10);
564         offset_third.Z = rangelim(offset_third.Z,-5,5);
565         /* TODO: if possible: improve the camera colision detetion to allow Y <= -1.5) */
566         offset_third.Y = rangelim(offset_third.Y,-10,15); //1.5*BS
567
568         getServer(L)->setPlayerEyeOffset(player, offset_first, offset_third);
569         lua_pushboolean(L, true);
570         return 1;
571 }
572
573 // get_eye_offset(self)
574 int ObjectRef::l_get_eye_offset(lua_State *L)
575 {
576         NO_MAP_LOCK_REQUIRED;
577         ObjectRef *ref = checkobject(L, 1);
578         RemotePlayer *player = getplayer(ref);
579         if (player == NULL)
580                 return 0;
581         // Do it
582         push_v3f(L, player->eye_offset_first);
583         push_v3f(L, player->eye_offset_third);
584         return 2;
585 }
586
587 // send_mapblock(self, pos)
588 int ObjectRef::l_send_mapblock(lua_State *L)
589 {
590         NO_MAP_LOCK_REQUIRED;
591         ObjectRef *ref = checkobject(L, 1);
592
593         RemotePlayer *player = getplayer(ref);
594         if (!player)
595                 return 0;
596         v3s16 p = read_v3s16(L, 2);
597
598         session_t peer_id = player->getPeerId();
599         bool r = getServer(L)->SendBlock(peer_id, p);
600
601         lua_pushboolean(L, r);
602         return 1;
603 }
604
605 // set_animation_frame_speed(self, frame_speed)
606 int ObjectRef::l_set_animation_frame_speed(lua_State *L)
607 {
608         NO_MAP_LOCK_REQUIRED;
609         ObjectRef *ref = checkobject(L, 1);
610         ServerActiveObject *co = getobject(ref);
611         if (co == NULL)
612                 return 0;
613
614         // Do it
615         if (!lua_isnil(L, 2)) {
616                 float frame_speed = lua_tonumber(L, 2);
617                 co->setAnimationSpeed(frame_speed);
618                 lua_pushboolean(L, true);
619         } else {
620                 lua_pushboolean(L, false);
621         }
622         return 1;
623 }
624
625 // set_bone_position(self, std::string bone, v3f position, v3f rotation)
626 int ObjectRef::l_set_bone_position(lua_State *L)
627 {
628         NO_MAP_LOCK_REQUIRED;
629         ObjectRef *ref = checkobject(L, 1);
630         ServerActiveObject *co = getobject(ref);
631         if (co == NULL) return 0;
632         // Do it
633         std::string bone;
634         if (!lua_isnil(L, 2))
635                 bone = readParam<std::string>(L, 2);
636         v3f position = v3f(0, 0, 0);
637         if (!lua_isnil(L, 3))
638                 position = check_v3f(L, 3);
639         v3f rotation = v3f(0, 0, 0);
640         if (!lua_isnil(L, 4))
641                 rotation = check_v3f(L, 4);
642         co->setBonePosition(bone, position, rotation);
643         return 0;
644 }
645
646 // get_bone_position(self, bone)
647 int ObjectRef::l_get_bone_position(lua_State *L)
648 {
649         NO_MAP_LOCK_REQUIRED;
650         ObjectRef *ref = checkobject(L, 1);
651         ServerActiveObject *co = getobject(ref);
652         if (co == NULL)
653                 return 0;
654         // Do it
655         std::string bone;
656         if (!lua_isnil(L, 2))
657                 bone = readParam<std::string>(L, 2);
658
659         v3f position = v3f(0, 0, 0);
660         v3f rotation = v3f(0, 0, 0);
661         co->getBonePosition(bone, &position, &rotation);
662
663         push_v3f(L, position);
664         push_v3f(L, rotation);
665         return 2;
666 }
667
668 // set_attach(self, parent, bone, position, rotation)
669 int ObjectRef::l_set_attach(lua_State *L)
670 {
671         GET_ENV_PTR;
672
673         ObjectRef *ref = checkobject(L, 1);
674         ObjectRef *parent_ref = checkobject(L, 2);
675         ServerActiveObject *co = getobject(ref);
676         ServerActiveObject *parent = getobject(parent_ref);
677         if (co == NULL)
678                 return 0;
679         if (parent == NULL)
680                 return 0;
681         // Do it
682         int parent_id = 0;
683         std::string bone;
684         v3f position = v3f(0, 0, 0);
685         v3f rotation = v3f(0, 0, 0);
686         co->getAttachment(&parent_id, &bone, &position, &rotation);
687         if (parent_id) {
688                 ServerActiveObject *old_parent = env->getActiveObject(parent_id);
689                 old_parent->removeAttachmentChild(co->getId());
690         }
691
692         bone = "";
693         if (!lua_isnil(L, 3))
694                 bone = readParam<std::string>(L, 3);
695         position = v3f(0, 0, 0);
696         if (!lua_isnil(L, 4))
697                 position = read_v3f(L, 4);
698         rotation = v3f(0, 0, 0);
699         if (!lua_isnil(L, 5))
700                 rotation = read_v3f(L, 5);
701         co->setAttachment(parent->getId(), bone, position, rotation);
702         parent->addAttachmentChild(co->getId());
703         return 0;
704 }
705
706 // get_attach(self)
707 int ObjectRef::l_get_attach(lua_State *L)
708 {
709         GET_ENV_PTR;
710
711         ObjectRef *ref = checkobject(L, 1);
712         ServerActiveObject *co = getobject(ref);
713         if (co == NULL)
714                 return 0;
715
716         // Do it
717         int parent_id = 0;
718         std::string bone;
719         v3f position = v3f(0, 0, 0);
720         v3f rotation = v3f(0, 0, 0);
721         co->getAttachment(&parent_id, &bone, &position, &rotation);
722         if (!parent_id)
723                 return 0;
724         ServerActiveObject *parent = env->getActiveObject(parent_id);
725
726         getScriptApiBase(L)->objectrefGetOrCreate(L, parent);
727         lua_pushlstring(L, bone.c_str(), bone.size());
728         push_v3f(L, position);
729         push_v3f(L, rotation);
730         return 4;
731 }
732
733 // set_detach(self)
734 int ObjectRef::l_set_detach(lua_State *L)
735 {
736         GET_ENV_PTR;
737
738         ObjectRef *ref = checkobject(L, 1);
739         ServerActiveObject *co = getobject(ref);
740         if (co == NULL)
741                 return 0;
742
743         co->clearParentAttachment();
744         return 0;
745 }
746
747 // set_properties(self, properties)
748 int ObjectRef::l_set_properties(lua_State *L)
749 {
750         NO_MAP_LOCK_REQUIRED;
751         ObjectRef *ref = checkobject(L, 1);
752         ServerActiveObject *co = getobject(ref);
753         if (!co)
754                 return 0;
755
756         ObjectProperties *prop = co->accessObjectProperties();
757         if (!prop)
758                 return 0;
759
760         read_object_properties(L, 2, prop, getServer(L)->idef());
761
762         PlayerSAO *player = getplayersao(ref);
763
764         if (prop->hp_max < co->getHP()) {
765                 PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP);
766                 co->setHP(prop->hp_max, reason);
767                 if (player)
768                         getServer(L)->SendPlayerHPOrDie(player, reason);
769         }
770
771         if (player && prop->breath_max < player->getBreath())
772                 player->setBreath(prop->breath_max);
773
774         co->notifyObjectPropertiesModified();
775         return 0;
776 }
777
778 // get_properties(self)
779 int ObjectRef::l_get_properties(lua_State *L)
780 {
781         NO_MAP_LOCK_REQUIRED;
782         ObjectRef *ref = checkobject(L, 1);
783         ServerActiveObject *co = getobject(ref);
784         if (co == NULL)
785                 return 0;
786         ObjectProperties *prop = co->accessObjectProperties();
787         if (!prop)
788                 return 0;
789         push_object_properties(L, prop);
790         return 1;
791 }
792
793 // is_player(self)
794 int ObjectRef::l_is_player(lua_State *L)
795 {
796         NO_MAP_LOCK_REQUIRED;
797         ObjectRef *ref = checkobject(L, 1);
798         RemotePlayer *player = getplayer(ref);
799         lua_pushboolean(L, (player != NULL));
800         return 1;
801 }
802
803 // set_nametag_attributes(self, attributes)
804 int ObjectRef::l_set_nametag_attributes(lua_State *L)
805 {
806         NO_MAP_LOCK_REQUIRED;
807         ObjectRef *ref = checkobject(L, 1);
808         ServerActiveObject *co = getobject(ref);
809
810         if (co == NULL)
811                 return 0;
812         ObjectProperties *prop = co->accessObjectProperties();
813         if (!prop)
814                 return 0;
815
816         lua_getfield(L, 2, "color");
817         if (!lua_isnil(L, -1)) {
818                 video::SColor color = prop->nametag_color;
819                 read_color(L, -1, &color);
820                 prop->nametag_color = color;
821         }
822         lua_pop(L, 1);
823
824         std::string nametag = getstringfield_default(L, 2, "text", "");
825         prop->nametag = nametag;
826
827         co->notifyObjectPropertiesModified();
828         lua_pushboolean(L, true);
829         return 1;
830 }
831
832 // get_nametag_attributes(self)
833 int ObjectRef::l_get_nametag_attributes(lua_State *L)
834 {
835         NO_MAP_LOCK_REQUIRED;
836         ObjectRef *ref = checkobject(L, 1);
837         ServerActiveObject *co = getobject(ref);
838
839         if (co == NULL)
840                 return 0;
841         ObjectProperties *prop = co->accessObjectProperties();
842         if (!prop)
843                 return 0;
844
845         video::SColor color = prop->nametag_color;
846
847         lua_newtable(L);
848         push_ARGB8(L, color);
849         lua_setfield(L, -2, "color");
850         lua_pushstring(L, prop->nametag.c_str());
851         lua_setfield(L, -2, "text");
852         return 1;
853 }
854
855 /* LuaEntitySAO-only */
856
857 // set_velocity(self, {x=num, y=num, z=num})
858 int ObjectRef::l_set_velocity(lua_State *L)
859 {
860         NO_MAP_LOCK_REQUIRED;
861         ObjectRef *ref = checkobject(L, 1);
862         LuaEntitySAO *co = getluaobject(ref);
863         if (co == NULL) return 0;
864         v3f pos = checkFloatPos(L, 2);
865         // Do it
866         co->setVelocity(pos);
867         return 0;
868 }
869
870 // add_velocity(self, {x=num, y=num, z=num})
871 int ObjectRef::l_add_velocity(lua_State *L)
872 {
873         NO_MAP_LOCK_REQUIRED;
874         ObjectRef *ref = checkobject(L, 1);
875         LuaEntitySAO *co = getluaobject(ref);
876         if (!co)
877                 return 0;
878         v3f pos = checkFloatPos(L, 2);
879         // Do it
880         co->addVelocity(pos);
881         return 0;
882 }
883
884 // get_velocity(self)
885 int ObjectRef::l_get_velocity(lua_State *L)
886 {
887         NO_MAP_LOCK_REQUIRED;
888         ObjectRef *ref = checkobject(L, 1);
889         LuaEntitySAO *co = getluaobject(ref);
890         if (co == NULL) return 0;
891         // Do it
892         v3f v = co->getVelocity();
893         pushFloatPos(L, v);
894         return 1;
895 }
896
897 // set_acceleration(self, {x=num, y=num, z=num})
898 int ObjectRef::l_set_acceleration(lua_State *L)
899 {
900         NO_MAP_LOCK_REQUIRED;
901         ObjectRef *ref = checkobject(L, 1);
902         LuaEntitySAO *co = getluaobject(ref);
903         if (co == NULL) return 0;
904         // pos
905         v3f pos = checkFloatPos(L, 2);
906         // Do it
907         co->setAcceleration(pos);
908         return 0;
909 }
910
911 // get_acceleration(self)
912 int ObjectRef::l_get_acceleration(lua_State *L)
913 {
914         NO_MAP_LOCK_REQUIRED;
915         ObjectRef *ref = checkobject(L, 1);
916         LuaEntitySAO *co = getluaobject(ref);
917         if (co == NULL) return 0;
918         // Do it
919         v3f v = co->getAcceleration();
920         pushFloatPos(L, v);
921         return 1;
922 }
923
924 // set_rotation(self, {x=num, y=num, z=num})
925 // Each 'num' is in radians
926 int ObjectRef::l_set_rotation(lua_State *L)
927 {
928         NO_MAP_LOCK_REQUIRED;
929         ObjectRef *ref = checkobject(L, 1);
930         LuaEntitySAO *co = getluaobject(ref);
931         if (!co)
932                 return 0;
933
934         v3f rotation = check_v3f(L, 2) * core::RADTODEG;
935         co->setRotation(rotation);
936         return 0;
937 }
938
939 // get_rotation(self)
940 // returns: {x=num, y=num, z=num}
941 // Each 'num' is in radians
942 int ObjectRef::l_get_rotation(lua_State *L)
943 {
944         NO_MAP_LOCK_REQUIRED;
945         ObjectRef *ref = checkobject(L, 1);
946         LuaEntitySAO *co = getluaobject(ref);
947         if (!co)
948                 return 0;
949
950         lua_newtable(L);
951         v3f rotation = co->getRotation() * core::DEGTORAD;
952         push_v3f(L, rotation);
953         return 1;
954 }
955
956 // set_yaw(self, radians)
957 int ObjectRef::l_set_yaw(lua_State *L)
958 {
959         NO_MAP_LOCK_REQUIRED;
960         ObjectRef *ref = checkobject(L, 1);
961         LuaEntitySAO *co = getluaobject(ref);
962
963         if (co == NULL) return 0;
964         if (isNaN(L, 2))
965                 throw LuaError("ObjectRef::set_yaw: NaN value is not allowed.");
966
967         float yaw = readParam<float>(L, 2) * core::RADTODEG;
968         co->setRotation(v3f(0, yaw, 0));
969         return 0;
970 }
971
972 // get_yaw(self)
973 int ObjectRef::l_get_yaw(lua_State *L)
974 {
975         NO_MAP_LOCK_REQUIRED;
976         ObjectRef *ref = checkobject(L, 1);
977         LuaEntitySAO *co = getluaobject(ref);
978         if (!co)
979                 return 0;
980
981         float yaw = co->getRotation().Y * core::DEGTORAD;
982         lua_pushnumber(L, yaw);
983         return 1;
984 }
985
986 // set_texture_mod(self, mod)
987 int ObjectRef::l_set_texture_mod(lua_State *L)
988 {
989         NO_MAP_LOCK_REQUIRED;
990         ObjectRef *ref = checkobject(L, 1);
991         LuaEntitySAO *co = getluaobject(ref);
992         if (co == NULL) return 0;
993         // Do it
994         std::string mod = luaL_checkstring(L, 2);
995         co->setTextureMod(mod);
996         return 0;
997 }
998
999 // get_texture_mod(self)
1000 int ObjectRef::l_get_texture_mod(lua_State *L)
1001 {
1002         NO_MAP_LOCK_REQUIRED;
1003         ObjectRef *ref = checkobject(L, 1);
1004         LuaEntitySAO *co = getluaobject(ref);
1005         if (co == NULL) return 0;
1006         // Do it
1007         std::string mod = co->getTextureMod();
1008         lua_pushstring(L, mod.c_str());
1009         return 1;
1010 }
1011
1012 // set_sprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
1013 //           select_horiz_by_yawpitch=false)
1014 int ObjectRef::l_set_sprite(lua_State *L)
1015 {
1016         NO_MAP_LOCK_REQUIRED;
1017         ObjectRef *ref = checkobject(L, 1);
1018         LuaEntitySAO *co = getluaobject(ref);
1019         if (co == NULL) return 0;
1020         // Do it
1021         v2s16 p(0,0);
1022         if (!lua_isnil(L, 2))
1023                 p = readParam<v2s16>(L, 2);
1024         int num_frames = 1;
1025         if (!lua_isnil(L, 3))
1026                 num_frames = lua_tonumber(L, 3);
1027         float framelength = 0.2;
1028         if (!lua_isnil(L, 4))
1029                 framelength = lua_tonumber(L, 4);
1030         bool select_horiz_by_yawpitch = false;
1031         if (!lua_isnil(L, 5))
1032                 select_horiz_by_yawpitch = readParam<bool>(L, 5);
1033         co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
1034         return 0;
1035 }
1036
1037 // DEPRECATED
1038 // get_entity_name(self)
1039 int ObjectRef::l_get_entity_name(lua_State *L)
1040 {
1041         NO_MAP_LOCK_REQUIRED;
1042         ObjectRef *ref = checkobject(L, 1);
1043         LuaEntitySAO *co = getluaobject(ref);
1044         log_deprecated(L,"Deprecated call to \"get_entity_name");
1045         if (co == NULL) return 0;
1046         // Do it
1047         std::string name = co->getName();
1048         lua_pushstring(L, name.c_str());
1049         return 1;
1050 }
1051
1052 // get_luaentity(self)
1053 int ObjectRef::l_get_luaentity(lua_State *L)
1054 {
1055         NO_MAP_LOCK_REQUIRED;
1056         ObjectRef *ref = checkobject(L, 1);
1057         LuaEntitySAO *co = getluaobject(ref);
1058         if (co == NULL) return 0;
1059         // Do it
1060         luaentity_get(L, co->getId());
1061         return 1;
1062 }
1063
1064 /* Player-only */
1065
1066 // is_player_connected(self)
1067 int ObjectRef::l_is_player_connected(lua_State *L)
1068 {
1069         NO_MAP_LOCK_REQUIRED;
1070         ObjectRef *ref = checkobject(L, 1);
1071         RemotePlayer *player = getplayer(ref);
1072         lua_pushboolean(L, (player != NULL && player->getPeerId() != PEER_ID_INEXISTENT));
1073         return 1;
1074 }
1075
1076 // get_player_name(self)
1077 int ObjectRef::l_get_player_name(lua_State *L)
1078 {
1079         NO_MAP_LOCK_REQUIRED;
1080         ObjectRef *ref = checkobject(L, 1);
1081         RemotePlayer *player = getplayer(ref);
1082         if (player == NULL) {
1083                 lua_pushlstring(L, "", 0);
1084                 return 1;
1085         }
1086         // Do it
1087         lua_pushstring(L, player->getName());
1088         return 1;
1089 }
1090
1091 // get_player_velocity(self)
1092 int ObjectRef::l_get_player_velocity(lua_State *L)
1093 {
1094         NO_MAP_LOCK_REQUIRED;
1095         ObjectRef *ref = checkobject(L, 1);
1096         RemotePlayer *player = getplayer(ref);
1097         if (player == NULL) {
1098                 lua_pushnil(L);
1099                 return 1;
1100         }
1101         // Do it
1102         push_v3f(L, player->getSpeed() / BS);
1103         return 1;
1104 }
1105
1106 // get_look_dir(self)
1107 int ObjectRef::l_get_look_dir(lua_State *L)
1108 {
1109         NO_MAP_LOCK_REQUIRED;
1110         ObjectRef *ref = checkobject(L, 1);
1111         PlayerSAO* co = getplayersao(ref);
1112         if (co == NULL) return 0;
1113         // Do it
1114         float pitch = co->getRadLookPitchDep();
1115         float yaw = co->getRadYawDep();
1116         v3f v(std::cos(pitch) * std::cos(yaw), std::sin(pitch), std::cos(pitch) *
1117                 std::sin(yaw));
1118         push_v3f(L, v);
1119         return 1;
1120 }
1121
1122 // DEPRECATED
1123 // get_look_pitch(self)
1124 int ObjectRef::l_get_look_pitch(lua_State *L)
1125 {
1126         NO_MAP_LOCK_REQUIRED;
1127
1128         log_deprecated(L,
1129                 "Deprecated call to get_look_pitch, use get_look_vertical instead");
1130
1131         ObjectRef *ref = checkobject(L, 1);
1132         PlayerSAO* co = getplayersao(ref);
1133         if (co == NULL) return 0;
1134         // Do it
1135         lua_pushnumber(L, co->getRadLookPitchDep());
1136         return 1;
1137 }
1138
1139 // DEPRECATED
1140 // get_look_yaw(self)
1141 int ObjectRef::l_get_look_yaw(lua_State *L)
1142 {
1143         NO_MAP_LOCK_REQUIRED;
1144
1145         log_deprecated(L,
1146                 "Deprecated call to get_look_yaw, use get_look_horizontal instead");
1147
1148         ObjectRef *ref = checkobject(L, 1);
1149         PlayerSAO* co = getplayersao(ref);
1150         if (co == NULL) return 0;
1151         // Do it
1152         lua_pushnumber(L, co->getRadYawDep());
1153         return 1;
1154 }
1155
1156 // get_look_pitch2(self)
1157 int ObjectRef::l_get_look_vertical(lua_State *L)
1158 {
1159         NO_MAP_LOCK_REQUIRED;
1160         ObjectRef *ref = checkobject(L, 1);
1161         PlayerSAO* co = getplayersao(ref);
1162         if (co == NULL) return 0;
1163         // Do it
1164         lua_pushnumber(L, co->getRadLookPitch());
1165         return 1;
1166 }
1167
1168 // get_look_yaw2(self)
1169 int ObjectRef::l_get_look_horizontal(lua_State *L)
1170 {
1171         NO_MAP_LOCK_REQUIRED;
1172         ObjectRef *ref = checkobject(L, 1);
1173         PlayerSAO* co = getplayersao(ref);
1174         if (co == NULL) return 0;
1175         // Do it
1176         lua_pushnumber(L, co->getRadRotation().Y);
1177         return 1;
1178 }
1179
1180 // set_look_vertical(self, radians)
1181 int ObjectRef::l_set_look_vertical(lua_State *L)
1182 {
1183         NO_MAP_LOCK_REQUIRED;
1184         ObjectRef *ref = checkobject(L, 1);
1185         PlayerSAO* co = getplayersao(ref);
1186         if (co == NULL) return 0;
1187         float pitch = readParam<float>(L, 2) * core::RADTODEG;
1188         // Do it
1189         co->setLookPitchAndSend(pitch);
1190         return 1;
1191 }
1192
1193 // set_look_horizontal(self, radians)
1194 int ObjectRef::l_set_look_horizontal(lua_State *L)
1195 {
1196         NO_MAP_LOCK_REQUIRED;
1197         ObjectRef *ref = checkobject(L, 1);
1198         PlayerSAO* co = getplayersao(ref);
1199         if (co == NULL) return 0;
1200         float yaw = readParam<float>(L, 2) * core::RADTODEG;
1201         // Do it
1202         co->setPlayerYawAndSend(yaw);
1203         return 1;
1204 }
1205
1206 // DEPRECATED
1207 // set_look_pitch(self, radians)
1208 int ObjectRef::l_set_look_pitch(lua_State *L)
1209 {
1210         NO_MAP_LOCK_REQUIRED;
1211
1212         log_deprecated(L,
1213                 "Deprecated call to set_look_pitch, use set_look_vertical instead.");
1214
1215         ObjectRef *ref = checkobject(L, 1);
1216         PlayerSAO* co = getplayersao(ref);
1217         if (co == NULL) return 0;
1218         float pitch = readParam<float>(L, 2) * core::RADTODEG;
1219         // Do it
1220         co->setLookPitchAndSend(pitch);
1221         return 1;
1222 }
1223
1224 // DEPRECATED
1225 // set_look_yaw(self, radians)
1226 int ObjectRef::l_set_look_yaw(lua_State *L)
1227 {
1228         NO_MAP_LOCK_REQUIRED;
1229
1230         log_deprecated(L,
1231                 "Deprecated call to set_look_yaw, use set_look_horizontal instead.");
1232
1233         ObjectRef *ref = checkobject(L, 1);
1234         PlayerSAO* co = getplayersao(ref);
1235         if (co == NULL) return 0;
1236         float yaw = readParam<float>(L, 2) * core::RADTODEG;
1237         // Do it
1238         co->setPlayerYawAndSend(yaw);
1239         return 1;
1240 }
1241
1242 // set_breath(self, breath)
1243 int ObjectRef::l_set_breath(lua_State *L)
1244 {
1245         NO_MAP_LOCK_REQUIRED;
1246         ObjectRef *ref = checkobject(L, 1);
1247         PlayerSAO* co = getplayersao(ref);
1248         if (co == NULL) return 0;
1249         u16 breath = luaL_checknumber(L, 2);
1250         co->setBreath(breath);
1251
1252         return 0;
1253 }
1254
1255 // get_breath(self)
1256 int ObjectRef::l_get_breath(lua_State *L)
1257 {
1258         NO_MAP_LOCK_REQUIRED;
1259         ObjectRef *ref = checkobject(L, 1);
1260         PlayerSAO* co = getplayersao(ref);
1261         if (co == NULL) return 0;
1262         // Do it
1263         u16 breath = co->getBreath();
1264         lua_pushinteger (L, breath);
1265         return 1;
1266 }
1267
1268 // set_attribute(self, attribute, value)
1269 int ObjectRef::l_set_attribute(lua_State *L)
1270 {
1271         log_deprecated(L,
1272                 "Deprecated call to set_attribute, use MetaDataRef methods instead.");
1273
1274         ObjectRef *ref = checkobject(L, 1);
1275         PlayerSAO* co = getplayersao(ref);
1276         if (co == NULL)
1277                 return 0;
1278
1279         std::string attr = luaL_checkstring(L, 2);
1280         if (lua_isnil(L, 3)) {
1281                 co->getMeta().removeString(attr);
1282         } else {
1283                 std::string value = luaL_checkstring(L, 3);
1284                 co->getMeta().setString(attr, value);
1285         }
1286         return 1;
1287 }
1288
1289 // get_attribute(self, attribute)
1290 int ObjectRef::l_get_attribute(lua_State *L)
1291 {
1292         log_deprecated(L,
1293                 "Deprecated call to get_attribute, use MetaDataRef methods instead.");
1294
1295         ObjectRef *ref = checkobject(L, 1);
1296         PlayerSAO* co = getplayersao(ref);
1297         if (co == NULL)
1298                 return 0;
1299
1300         std::string attr = luaL_checkstring(L, 2);
1301
1302         std::string value;
1303         if (co->getMeta().getStringToRef(attr, value)) {
1304                 lua_pushstring(L, value.c_str());
1305                 return 1;
1306         }
1307
1308         return 0;
1309 }
1310
1311
1312 // get_meta(self, attribute)
1313 int ObjectRef::l_get_meta(lua_State *L)
1314 {
1315         ObjectRef *ref = checkobject(L, 1);
1316         PlayerSAO *co = getplayersao(ref);
1317         if (co == NULL)
1318                 return 0;
1319
1320         PlayerMetaRef::create(L, &co->getMeta());
1321         return 1;
1322 }
1323
1324
1325 // set_inventory_formspec(self, formspec)
1326 int ObjectRef::l_set_inventory_formspec(lua_State *L)
1327 {
1328         NO_MAP_LOCK_REQUIRED;
1329         ObjectRef *ref = checkobject(L, 1);
1330         RemotePlayer *player = getplayer(ref);
1331         if (player == NULL) return 0;
1332         std::string formspec = luaL_checkstring(L, 2);
1333
1334         player->inventory_formspec = formspec;
1335         getServer(L)->reportInventoryFormspecModified(player->getName());
1336         lua_pushboolean(L, true);
1337         return 1;
1338 }
1339
1340 // get_inventory_formspec(self) -> formspec
1341 int ObjectRef::l_get_inventory_formspec(lua_State *L)
1342 {
1343         NO_MAP_LOCK_REQUIRED;
1344         ObjectRef *ref = checkobject(L, 1);
1345         RemotePlayer *player = getplayer(ref);
1346         if (player == NULL) return 0;
1347
1348         std::string formspec = player->inventory_formspec;
1349         lua_pushlstring(L, formspec.c_str(), formspec.size());
1350         return 1;
1351 }
1352
1353 // set_formspec_prepend(self, formspec)
1354 int ObjectRef::l_set_formspec_prepend(lua_State *L)
1355 {
1356         NO_MAP_LOCK_REQUIRED;
1357         ObjectRef *ref = checkobject(L, 1);
1358         RemotePlayer *player = getplayer(ref);
1359         if (player == NULL)
1360                 return 0;
1361
1362         std::string formspec = luaL_checkstring(L, 2);
1363
1364         player->formspec_prepend = formspec;
1365         getServer(L)->reportFormspecPrependModified(player->getName());
1366         lua_pushboolean(L, true);
1367         return 1;
1368 }
1369
1370 // get_formspec_prepend(self) -> formspec
1371 int ObjectRef::l_get_formspec_prepend(lua_State *L)
1372 {
1373         NO_MAP_LOCK_REQUIRED;
1374         ObjectRef *ref = checkobject(L, 1);
1375         RemotePlayer *player = getplayer(ref);
1376         if (player == NULL)
1377                  return 0;
1378
1379         std::string formspec = player->formspec_prepend;
1380         lua_pushlstring(L, formspec.c_str(), formspec.size());
1381         return 1;
1382 }
1383
1384 // get_player_control(self)
1385 int ObjectRef::l_get_player_control(lua_State *L)
1386 {
1387         NO_MAP_LOCK_REQUIRED;
1388         ObjectRef *ref = checkobject(L, 1);
1389         RemotePlayer *player = getplayer(ref);
1390         if (player == NULL) {
1391                 lua_pushlstring(L, "", 0);
1392                 return 1;
1393         }
1394
1395         const PlayerControl &control = player->getPlayerControl();
1396         lua_newtable(L);
1397         lua_pushboolean(L, control.up);
1398         lua_setfield(L, -2, "up");
1399         lua_pushboolean(L, control.down);
1400         lua_setfield(L, -2, "down");
1401         lua_pushboolean(L, control.left);
1402         lua_setfield(L, -2, "left");
1403         lua_pushboolean(L, control.right);
1404         lua_setfield(L, -2, "right");
1405         lua_pushboolean(L, control.jump);
1406         lua_setfield(L, -2, "jump");
1407         lua_pushboolean(L, control.aux1);
1408         lua_setfield(L, -2, "aux1");
1409         lua_pushboolean(L, control.sneak);
1410         lua_setfield(L, -2, "sneak");
1411         lua_pushboolean(L, control.LMB);
1412         lua_setfield(L, -2, "LMB");
1413         lua_pushboolean(L, control.RMB);
1414         lua_setfield(L, -2, "RMB");
1415         return 1;
1416 }
1417
1418 // get_player_control_bits(self)
1419 int ObjectRef::l_get_player_control_bits(lua_State *L)
1420 {
1421         NO_MAP_LOCK_REQUIRED;
1422         ObjectRef *ref = checkobject(L, 1);
1423         RemotePlayer *player = getplayer(ref);
1424         if (player == NULL) {
1425                 lua_pushlstring(L, "", 0);
1426                 return 1;
1427         }
1428         // Do it
1429         lua_pushnumber(L, player->keyPressed);
1430         return 1;
1431 }
1432
1433 // hud_add(self, form)
1434 int ObjectRef::l_hud_add(lua_State *L)
1435 {
1436         NO_MAP_LOCK_REQUIRED;
1437         ObjectRef *ref = checkobject(L, 1);
1438         RemotePlayer *player = getplayer(ref);
1439         if (player == NULL)
1440                 return 0;
1441
1442         HudElement *elem = new HudElement;
1443         read_hud_element(L, elem);
1444
1445         u32 id = getServer(L)->hudAdd(player, elem);
1446         if (id == U32_MAX) {
1447                 delete elem;
1448                 return 0;
1449         }
1450
1451         lua_pushnumber(L, id);
1452         return 1;
1453 }
1454
1455 // hud_remove(self, id)
1456 int ObjectRef::l_hud_remove(lua_State *L)
1457 {
1458         NO_MAP_LOCK_REQUIRED;
1459         ObjectRef *ref = checkobject(L, 1);
1460         RemotePlayer *player = getplayer(ref);
1461         if (player == NULL)
1462                 return 0;
1463
1464         u32 id = -1;
1465         if (!lua_isnil(L, 2))
1466                 id = lua_tonumber(L, 2);
1467
1468         if (!getServer(L)->hudRemove(player, id))
1469                 return 0;
1470
1471         lua_pushboolean(L, true);
1472         return 1;
1473 }
1474
1475 // hud_change(self, id, stat, data)
1476 int ObjectRef::l_hud_change(lua_State *L)
1477 {
1478         NO_MAP_LOCK_REQUIRED;
1479         ObjectRef *ref = checkobject(L, 1);
1480         RemotePlayer *player = getplayer(ref);
1481         if (player == NULL)
1482                 return 0;
1483
1484         u32 id = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : -1;
1485
1486         HudElement *e = player->getHud(id);
1487         if (!e)
1488                 return 0;
1489
1490         void *value = NULL;
1491         HudElementStat stat = read_hud_change(L, e, &value);
1492
1493         getServer(L)->hudChange(player, id, stat, value);
1494
1495         lua_pushboolean(L, true);
1496         return 1;
1497 }
1498
1499 // hud_get(self, id)
1500 int ObjectRef::l_hud_get(lua_State *L)
1501 {
1502         NO_MAP_LOCK_REQUIRED;
1503         ObjectRef *ref = checkobject(L, 1);
1504         RemotePlayer *player = getplayer(ref);
1505         if (player == NULL)
1506                 return 0;
1507
1508         u32 id = lua_tonumber(L, -1);
1509
1510         HudElement *e = player->getHud(id);
1511         if (!e)
1512                 return 0;
1513         push_hud_element(L, e);
1514         return 1;
1515 }
1516
1517 // hud_set_flags(self, flags)
1518 int ObjectRef::l_hud_set_flags(lua_State *L)
1519 {
1520         NO_MAP_LOCK_REQUIRED;
1521         ObjectRef *ref = checkobject(L, 1);
1522         RemotePlayer *player = getplayer(ref);
1523         if (player == NULL)
1524                 return 0;
1525
1526         u32 flags = 0;
1527         u32 mask  = 0;
1528         bool flag;
1529
1530         const EnumString *esp = es_HudBuiltinElement;
1531         for (int i = 0; esp[i].str; i++) {
1532                 if (getboolfield(L, 2, esp[i].str, flag)) {
1533                         flags |= esp[i].num * flag;
1534                         mask  |= esp[i].num;
1535                 }
1536         }
1537         if (!getServer(L)->hudSetFlags(player, flags, mask))
1538                 return 0;
1539
1540         lua_pushboolean(L, true);
1541         return 1;
1542 }
1543
1544 int ObjectRef::l_hud_get_flags(lua_State *L)
1545 {
1546         NO_MAP_LOCK_REQUIRED;
1547         ObjectRef *ref = checkobject(L, 1);
1548         RemotePlayer *player = getplayer(ref);
1549         if (player == NULL)
1550                 return 0;
1551
1552         lua_newtable(L);
1553         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE);
1554         lua_setfield(L, -2, "hotbar");
1555         lua_pushboolean(L, player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE);
1556         lua_setfield(L, -2, "healthbar");
1557         lua_pushboolean(L, player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE);
1558         lua_setfield(L, -2, "crosshair");
1559         lua_pushboolean(L, player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE);
1560         lua_setfield(L, -2, "wielditem");
1561         lua_pushboolean(L, player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE);
1562         lua_setfield(L, -2, "breathbar");
1563         lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
1564         lua_setfield(L, -2, "minimap");
1565         lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE);
1566         lua_setfield(L, -2, "minimap_radar");
1567
1568         return 1;
1569 }
1570
1571 // hud_set_hotbar_itemcount(self, hotbar_itemcount)
1572 int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
1573 {
1574         NO_MAP_LOCK_REQUIRED;
1575         ObjectRef *ref = checkobject(L, 1);
1576         RemotePlayer *player = getplayer(ref);
1577         if (player == NULL)
1578                 return 0;
1579
1580         s32 hotbar_itemcount = lua_tonumber(L, 2);
1581
1582         if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
1583                 return 0;
1584
1585         lua_pushboolean(L, true);
1586         return 1;
1587 }
1588
1589 // hud_get_hotbar_itemcount(self)
1590 int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
1591 {
1592         NO_MAP_LOCK_REQUIRED;
1593         ObjectRef *ref = checkobject(L, 1);
1594         RemotePlayer *player = getplayer(ref);
1595         if (player == NULL)
1596                 return 0;
1597
1598         lua_pushnumber(L, player->getHotbarItemcount());
1599         return 1;
1600 }
1601
1602 // hud_set_hotbar_image(self, name)
1603 int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
1604 {
1605         NO_MAP_LOCK_REQUIRED;
1606         ObjectRef *ref = checkobject(L, 1);
1607         RemotePlayer *player = getplayer(ref);
1608         if (player == NULL)
1609                 return 0;
1610
1611         std::string name = readParam<std::string>(L, 2);
1612
1613         getServer(L)->hudSetHotbarImage(player, name);
1614         return 1;
1615 }
1616
1617 // hud_get_hotbar_image(self)
1618 int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
1619 {
1620         NO_MAP_LOCK_REQUIRED;
1621         ObjectRef *ref = checkobject(L, 1);
1622         RemotePlayer *player = getplayer(ref);
1623         if (player == NULL)
1624                 return 0;
1625
1626         const std::string &name = player->getHotbarImage();
1627         lua_pushlstring(L, name.c_str(), name.size());
1628         return 1;
1629 }
1630
1631 // hud_set_hotbar_selected_image(self, name)
1632 int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
1633 {
1634         NO_MAP_LOCK_REQUIRED;
1635         ObjectRef *ref = checkobject(L, 1);
1636         RemotePlayer *player = getplayer(ref);
1637         if (player == NULL)
1638                 return 0;
1639
1640         std::string name = readParam<std::string>(L, 2);
1641
1642         getServer(L)->hudSetHotbarSelectedImage(player, name);
1643         return 1;
1644 }
1645
1646 // hud_get_hotbar_selected_image(self)
1647 int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
1648 {
1649         NO_MAP_LOCK_REQUIRED;
1650         ObjectRef *ref = checkobject(L, 1);
1651         RemotePlayer *player = getplayer(ref);
1652         if (player == NULL)
1653                 return 0;
1654
1655         const std::string &name = player->getHotbarSelectedImage();
1656         lua_pushlstring(L, name.c_str(), name.size());
1657         return 1;
1658 }
1659
1660 // set_sky(self, bgcolor, type, list, clouds = true)
1661 int ObjectRef::l_set_sky(lua_State *L)
1662 {
1663         NO_MAP_LOCK_REQUIRED;
1664         ObjectRef *ref = checkobject(L, 1);
1665         RemotePlayer *player = getplayer(ref);
1666         if (player == NULL)
1667                 return 0;
1668
1669         video::SColor bgcolor(255,255,255,255);
1670         read_color(L, 2, &bgcolor);
1671
1672         std::string type = luaL_checkstring(L, 3);
1673
1674         std::vector<std::string> params;
1675         if (lua_istable(L, 4)) {
1676                 lua_pushnil(L);
1677                 while (lua_next(L, 4) != 0) {
1678                         // key at index -2 and value at index -1
1679                         if (lua_isstring(L, -1))
1680                                 params.emplace_back(readParam<std::string>(L, -1));
1681                         else
1682                                 params.emplace_back("");
1683                         // removes value, keeps key for next iteration
1684                         lua_pop(L, 1);
1685                 }
1686         }
1687
1688         if (type == "skybox" && params.size() != 6)
1689                 throw LuaError("skybox expects 6 textures");
1690
1691         bool clouds = true;
1692         if (lua_isboolean(L, 5))
1693                 clouds = readParam<bool>(L, 5);
1694
1695         getServer(L)->setSky(player, bgcolor, type, params, clouds);
1696         lua_pushboolean(L, true);
1697         return 1;
1698 }
1699
1700 // get_sky(self)
1701 int ObjectRef::l_get_sky(lua_State *L)
1702 {
1703         NO_MAP_LOCK_REQUIRED;
1704         ObjectRef *ref = checkobject(L, 1);
1705         RemotePlayer *player = getplayer(ref);
1706         if (player == NULL)
1707                 return 0;
1708         video::SColor bgcolor(255, 255, 255, 255);
1709         std::string type;
1710         std::vector<std::string> params;
1711         bool clouds;
1712
1713         player->getSky(&bgcolor, &type, &params, &clouds);
1714         type = type.empty() ? "regular" : type;
1715
1716         push_ARGB8(L, bgcolor);
1717         lua_pushlstring(L, type.c_str(), type.size());
1718         lua_newtable(L);
1719         s16 i = 1;
1720         for (const std::string &param : params) {
1721                 lua_pushlstring(L, param.c_str(), param.size());
1722                 lua_rawseti(L, -2, i++);
1723         }
1724         lua_pushboolean(L, clouds);
1725         return 4;
1726 }
1727
1728 // set_clouds(self, {density=, color=, ambient=, height=, thickness=, speed=})
1729 int ObjectRef::l_set_clouds(lua_State *L)
1730 {
1731         NO_MAP_LOCK_REQUIRED;
1732         ObjectRef *ref = checkobject(L, 1);
1733         RemotePlayer *player = getplayer(ref);
1734         if (!player)
1735                 return 0;
1736         if (!lua_istable(L, 2))
1737                 return 0;
1738
1739         CloudParams cloud_params = player->getCloudParams();
1740
1741         cloud_params.density = getfloatfield_default(L, 2, "density", cloud_params.density);
1742
1743         lua_getfield(L, 2, "color");
1744         if (!lua_isnil(L, -1))
1745                 read_color(L, -1, &cloud_params.color_bright);
1746         lua_pop(L, 1);
1747         lua_getfield(L, 2, "ambient");
1748         if (!lua_isnil(L, -1))
1749                 read_color(L, -1, &cloud_params.color_ambient);
1750         lua_pop(L, 1);
1751
1752         cloud_params.height    = getfloatfield_default(L, 2, "height",    cloud_params.height   );
1753         cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness);
1754
1755         lua_getfield(L, 2, "speed");
1756         if (lua_istable(L, -1)) {
1757                 v2f new_speed;
1758                 new_speed.X = getfloatfield_default(L, -1, "x", 0);
1759                 new_speed.Y = getfloatfield_default(L, -1, "z", 0);
1760                 cloud_params.speed = new_speed;
1761         }
1762         lua_pop(L, 1);
1763
1764         getServer(L)->setClouds(player, cloud_params);
1765         lua_pushboolean(L, true);
1766         return 1;
1767 }
1768
1769 int ObjectRef::l_get_clouds(lua_State *L)
1770 {
1771         NO_MAP_LOCK_REQUIRED;
1772         ObjectRef *ref = checkobject(L, 1);
1773         RemotePlayer *player = getplayer(ref);
1774         if (!player)
1775                 return 0;
1776         const CloudParams &cloud_params = player->getCloudParams();
1777
1778         lua_newtable(L);
1779         lua_pushnumber(L, cloud_params.density);
1780         lua_setfield(L, -2, "density");
1781         push_ARGB8(L, cloud_params.color_bright);
1782         lua_setfield(L, -2, "color");
1783         push_ARGB8(L, cloud_params.color_ambient);
1784         lua_setfield(L, -2, "ambient");
1785         lua_pushnumber(L, cloud_params.height);
1786         lua_setfield(L, -2, "height");
1787         lua_pushnumber(L, cloud_params.thickness);
1788         lua_setfield(L, -2, "thickness");
1789         lua_newtable(L);
1790         lua_pushnumber(L, cloud_params.speed.X);
1791         lua_setfield(L, -2, "x");
1792         lua_pushnumber(L, cloud_params.speed.Y);
1793         lua_setfield(L, -2, "y");
1794         lua_setfield(L, -2, "speed");
1795
1796         return 1;
1797 }
1798
1799
1800 // override_day_night_ratio(self, brightness=0...1)
1801 int ObjectRef::l_override_day_night_ratio(lua_State *L)
1802 {
1803         NO_MAP_LOCK_REQUIRED;
1804         ObjectRef *ref = checkobject(L, 1);
1805         RemotePlayer *player = getplayer(ref);
1806         if (player == NULL)
1807                 return 0;
1808
1809         bool do_override = false;
1810         float ratio = 0.0f;
1811         if (!lua_isnil(L, 2)) {
1812                 do_override = true;
1813                 ratio = readParam<float>(L, 2);
1814         }
1815
1816         if (!getServer(L)->overrideDayNightRatio(player, do_override, ratio))
1817                 return 0;
1818
1819         lua_pushboolean(L, true);
1820         return 1;
1821 }
1822
1823 // get_day_night_ratio(self)
1824 int ObjectRef::l_get_day_night_ratio(lua_State *L)
1825 {
1826         NO_MAP_LOCK_REQUIRED;
1827         ObjectRef *ref = checkobject(L, 1);
1828         RemotePlayer *player = getplayer(ref);
1829         if (player == NULL)
1830                 return 0;
1831
1832         bool do_override;
1833         float ratio;
1834         player->getDayNightRatio(&do_override, &ratio);
1835
1836         if (do_override)
1837                 lua_pushnumber(L, ratio);
1838         else
1839                 lua_pushnil(L);
1840
1841         return 1;
1842 }
1843
1844 ObjectRef::ObjectRef(ServerActiveObject *object):
1845         m_object(object)
1846 {
1847         //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
1848 }
1849
1850 // Creates an ObjectRef and leaves it on top of stack
1851 // Not callable from Lua; all references are created on the C side.
1852 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
1853 {
1854         ObjectRef *o = new ObjectRef(object);
1855         //infostream<<"ObjectRef::create: o="<<o<<std::endl;
1856         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1857         luaL_getmetatable(L, className);
1858         lua_setmetatable(L, -2);
1859 }
1860
1861 void ObjectRef::set_null(lua_State *L)
1862 {
1863         ObjectRef *o = checkobject(L, -1);
1864         o->m_object = NULL;
1865 }
1866
1867 void ObjectRef::Register(lua_State *L)
1868 {
1869         lua_newtable(L);
1870         int methodtable = lua_gettop(L);
1871         luaL_newmetatable(L, className);
1872         int metatable = lua_gettop(L);
1873
1874         lua_pushliteral(L, "__metatable");
1875         lua_pushvalue(L, methodtable);
1876         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
1877
1878         lua_pushliteral(L, "__index");
1879         lua_pushvalue(L, methodtable);
1880         lua_settable(L, metatable);
1881
1882         lua_pushliteral(L, "__gc");
1883         lua_pushcfunction(L, gc_object);
1884         lua_settable(L, metatable);
1885
1886         lua_pop(L, 1);  // drop metatable
1887
1888         markAliasDeprecated(methods);
1889         luaL_openlib(L, 0, methods, 0);  // fill methodtable
1890         lua_pop(L, 1);  // drop methodtable
1891
1892         // Cannot be created from Lua
1893         //lua_register(L, className, create_object);
1894 }
1895
1896 const char ObjectRef::className[] = "ObjectRef";
1897 luaL_Reg ObjectRef::methods[] = {
1898         // ServerActiveObject
1899         luamethod(ObjectRef, remove),
1900         luamethod_aliased(ObjectRef, get_pos, getpos),
1901         luamethod_aliased(ObjectRef, set_pos, setpos),
1902         luamethod_aliased(ObjectRef, move_to, moveto),
1903         luamethod(ObjectRef, punch),
1904         luamethod(ObjectRef, right_click),
1905         luamethod(ObjectRef, set_hp),
1906         luamethod(ObjectRef, get_hp),
1907         luamethod(ObjectRef, get_inventory),
1908         luamethod(ObjectRef, get_wield_list),
1909         luamethod(ObjectRef, get_wield_index),
1910         luamethod(ObjectRef, get_wielded_item),
1911         luamethod(ObjectRef, set_wielded_item),
1912         luamethod(ObjectRef, set_armor_groups),
1913         luamethod(ObjectRef, get_armor_groups),
1914         luamethod(ObjectRef, set_animation),
1915         luamethod(ObjectRef, get_animation),
1916         luamethod(ObjectRef, set_animation_frame_speed),
1917         luamethod(ObjectRef, set_bone_position),
1918         luamethod(ObjectRef, get_bone_position),
1919         luamethod(ObjectRef, set_attach),
1920         luamethod(ObjectRef, get_attach),
1921         luamethod(ObjectRef, set_detach),
1922         luamethod(ObjectRef, set_properties),
1923         luamethod(ObjectRef, get_properties),
1924         luamethod(ObjectRef, set_nametag_attributes),
1925         luamethod(ObjectRef, get_nametag_attributes),
1926         // LuaEntitySAO-only
1927         luamethod_aliased(ObjectRef, set_velocity, setvelocity),
1928         luamethod(ObjectRef, add_velocity),
1929         luamethod_aliased(ObjectRef, get_velocity, getvelocity),
1930         luamethod_aliased(ObjectRef, set_acceleration, setacceleration),
1931         luamethod_aliased(ObjectRef, get_acceleration, getacceleration),
1932         luamethod_aliased(ObjectRef, set_yaw, setyaw),
1933         luamethod_aliased(ObjectRef, get_yaw, getyaw),
1934         luamethod(ObjectRef, set_rotation),
1935         luamethod(ObjectRef, get_rotation),
1936         luamethod_aliased(ObjectRef, set_texture_mod, settexturemod),
1937         luamethod_aliased(ObjectRef, set_sprite, setsprite),
1938         luamethod(ObjectRef, get_entity_name),
1939         luamethod(ObjectRef, get_luaentity),
1940         // Player-only
1941         luamethod(ObjectRef, is_player),
1942         luamethod(ObjectRef, is_player_connected),
1943         luamethod(ObjectRef, get_player_name),
1944         luamethod(ObjectRef, get_player_velocity),
1945         luamethod(ObjectRef, get_look_dir),
1946         luamethod(ObjectRef, get_look_pitch),
1947         luamethod(ObjectRef, get_look_yaw),
1948         luamethod(ObjectRef, get_look_vertical),
1949         luamethod(ObjectRef, get_look_horizontal),
1950         luamethod(ObjectRef, set_look_horizontal),
1951         luamethod(ObjectRef, set_look_vertical),
1952         luamethod(ObjectRef, set_look_yaw),
1953         luamethod(ObjectRef, set_look_pitch),
1954         luamethod(ObjectRef, get_breath),
1955         luamethod(ObjectRef, set_breath),
1956         luamethod(ObjectRef, get_attribute),
1957         luamethod(ObjectRef, set_attribute),
1958         luamethod(ObjectRef, get_meta),
1959         luamethod(ObjectRef, set_inventory_formspec),
1960         luamethod(ObjectRef, get_inventory_formspec),
1961         luamethod(ObjectRef, set_formspec_prepend),
1962         luamethod(ObjectRef, get_formspec_prepend),
1963         luamethod(ObjectRef, get_player_control),
1964         luamethod(ObjectRef, get_player_control_bits),
1965         luamethod(ObjectRef, set_physics_override),
1966         luamethod(ObjectRef, get_physics_override),
1967         luamethod(ObjectRef, hud_add),
1968         luamethod(ObjectRef, hud_remove),
1969         luamethod(ObjectRef, hud_change),
1970         luamethod(ObjectRef, hud_get),
1971         luamethod(ObjectRef, hud_set_flags),
1972         luamethod(ObjectRef, hud_get_flags),
1973         luamethod(ObjectRef, hud_set_hotbar_itemcount),
1974         luamethod(ObjectRef, hud_get_hotbar_itemcount),
1975         luamethod(ObjectRef, hud_set_hotbar_image),
1976         luamethod(ObjectRef, hud_get_hotbar_image),
1977         luamethod(ObjectRef, hud_set_hotbar_selected_image),
1978         luamethod(ObjectRef, hud_get_hotbar_selected_image),
1979         luamethod(ObjectRef, set_sky),
1980         luamethod(ObjectRef, get_sky),
1981         luamethod(ObjectRef, set_clouds),
1982         luamethod(ObjectRef, get_clouds),
1983         luamethod(ObjectRef, override_day_night_ratio),
1984         luamethod(ObjectRef, get_day_night_ratio),
1985         luamethod(ObjectRef, set_local_animation),
1986         luamethod(ObjectRef, get_local_animation),
1987         luamethod(ObjectRef, set_eye_offset),
1988         luamethod(ObjectRef, get_eye_offset),
1989         luamethod(ObjectRef, send_mapblock),
1990         {0,0}
1991 };