]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_object.cpp
Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenu
[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 "lua_api/l_internal.h"
22 #include "lua_api/l_inventory.h"
23 #include "lua_api/l_item.h"
24 #include "common/c_converter.h"
25 #include "common/c_content.h"
26 #include "log.h"
27 #include "tool.h"
28 #include "serverobject.h"
29 #include "content_object.h"
30 #include "content_sao.h"
31 #include "server.h"
32 #include "hud.h"
33
34
35 struct EnumString es_HudElementType[] =
36 {
37         {HUD_ELEM_IMAGE,     "image"},
38         {HUD_ELEM_TEXT,      "text"},
39         {HUD_ELEM_STATBAR,   "statbar"},
40         {HUD_ELEM_INVENTORY, "inventory"},
41 {0, NULL},
42 };
43
44 struct EnumString es_HudElementStat[] =
45 {
46         {HUD_STAT_POS,    "pos"},
47         {HUD_STAT_NAME,   "name"},
48         {HUD_STAT_SCALE,  "scale"},
49         {HUD_STAT_TEXT,   "text"},
50         {HUD_STAT_NUMBER, "number"},
51         {HUD_STAT_ITEM,   "item"},
52         {HUD_STAT_DIR,    "direction"},
53         {HUD_STAT_ALIGN,  "alignment"},
54         {HUD_STAT_OFFSET, "offset"},
55         {0, NULL},
56 };
57
58 struct EnumString es_HudBuiltinElement[] =
59 {
60         {HUD_FLAG_HOTBAR_VISIBLE,    "hotbar"},
61         {HUD_FLAG_HEALTHBAR_VISIBLE, "healthbar"},
62         {HUD_FLAG_CROSSHAIR_VISIBLE, "crosshair"},
63         {HUD_FLAG_WIELDITEM_VISIBLE, "wielditem"},
64         {HUD_FLAG_BREATHBAR_VISIBLE, "breathbar"},
65         {0, NULL},
66 };
67
68 /*
69         ObjectRef
70 */
71
72
73 ObjectRef* ObjectRef::checkobject(lua_State *L, int narg)
74 {
75         luaL_checktype(L, narg, LUA_TUSERDATA);
76         void *ud = luaL_checkudata(L, narg, className);
77         if(!ud) luaL_typerror(L, narg, className);
78         return *(ObjectRef**)ud;  // unbox pointer
79 }
80
81 ServerActiveObject* ObjectRef::getobject(ObjectRef *ref)
82 {
83         ServerActiveObject *co = ref->m_object;
84         return co;
85 }
86
87 LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
88 {
89         ServerActiveObject *obj = getobject(ref);
90         if(obj == NULL)
91                 return NULL;
92         if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
93                 return NULL;
94         return (LuaEntitySAO*)obj;
95 }
96
97 PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
98 {
99         ServerActiveObject *obj = getobject(ref);
100         if(obj == NULL)
101                 return NULL;
102         if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
103                 return NULL;
104         return (PlayerSAO*)obj;
105 }
106
107 Player* ObjectRef::getplayer(ObjectRef *ref)
108 {
109         PlayerSAO *playersao = getplayersao(ref);
110         if(playersao == NULL)
111                 return NULL;
112         return playersao->getPlayer();
113 }
114
115 // Exported functions
116
117 // garbage collector
118 int ObjectRef::gc_object(lua_State *L) {
119         ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
120         //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
121         delete o;
122         return 0;
123 }
124
125 // remove(self)
126 int ObjectRef::l_remove(lua_State *L)
127 {
128         NO_MAP_LOCK_REQUIRED;
129         ObjectRef *ref = checkobject(L, 1);
130         ServerActiveObject *co = getobject(ref);
131         if(co == NULL) return 0;
132         verbosestream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
133         co->m_removed = true;
134         return 0;
135 }
136
137 // getpos(self)
138 // returns: {x=num, y=num, z=num}
139 int ObjectRef::l_getpos(lua_State *L)
140 {
141         NO_MAP_LOCK_REQUIRED;
142         ObjectRef *ref = checkobject(L, 1);
143         ServerActiveObject *co = getobject(ref);
144         if(co == NULL) return 0;
145         v3f pos = co->getBasePosition() / BS;
146         lua_newtable(L);
147         lua_pushnumber(L, pos.X);
148         lua_setfield(L, -2, "x");
149         lua_pushnumber(L, pos.Y);
150         lua_setfield(L, -2, "y");
151         lua_pushnumber(L, pos.Z);
152         lua_setfield(L, -2, "z");
153         return 1;
154 }
155
156 // setpos(self, pos)
157 int ObjectRef::l_setpos(lua_State *L)
158 {
159         NO_MAP_LOCK_REQUIRED;
160         ObjectRef *ref = checkobject(L, 1);
161         //LuaEntitySAO *co = getluaobject(ref);
162         ServerActiveObject *co = getobject(ref);
163         if(co == NULL) return 0;
164         // pos
165         v3f pos = checkFloatPos(L, 2);
166         // Do it
167         co->setPos(pos);
168         return 0;
169 }
170
171 // moveto(self, pos, continuous=false)
172 int ObjectRef::l_moveto(lua_State *L)
173 {
174         NO_MAP_LOCK_REQUIRED;
175         ObjectRef *ref = checkobject(L, 1);
176         //LuaEntitySAO *co = getluaobject(ref);
177         ServerActiveObject *co = getobject(ref);
178         if(co == NULL) return 0;
179         // pos
180         v3f pos = checkFloatPos(L, 2);
181         // continuous
182         bool continuous = lua_toboolean(L, 3);
183         // Do it
184         co->moveTo(pos, continuous);
185         return 0;
186 }
187
188 // punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
189 int ObjectRef::l_punch(lua_State *L)
190 {
191         NO_MAP_LOCK_REQUIRED;
192         ObjectRef *ref = checkobject(L, 1);
193         ObjectRef *puncher_ref = checkobject(L, 2);
194         ServerActiveObject *co = getobject(ref);
195         ServerActiveObject *puncher = getobject(puncher_ref);
196         if(co == NULL) return 0;
197         if(puncher == NULL) return 0;
198         v3f dir;
199         if(lua_type(L, 5) != LUA_TTABLE)
200                 dir = co->getBasePosition() - puncher->getBasePosition();
201         else
202                 dir = read_v3f(L, 5);
203         float time_from_last_punch = 1000000;
204         if(lua_isnumber(L, 3))
205                 time_from_last_punch = lua_tonumber(L, 3);
206         ToolCapabilities toolcap = read_tool_capabilities(L, 4);
207         dir.normalize();
208         // Do it
209         co->punch(dir, &toolcap, puncher, time_from_last_punch);
210         return 0;
211 }
212
213 // right_click(self, clicker); clicker = an another ObjectRef
214 int ObjectRef::l_right_click(lua_State *L)
215 {
216         NO_MAP_LOCK_REQUIRED;
217         ObjectRef *ref = checkobject(L, 1);
218         ObjectRef *ref2 = checkobject(L, 2);
219         ServerActiveObject *co = getobject(ref);
220         ServerActiveObject *co2 = getobject(ref2);
221         if(co == NULL) return 0;
222         if(co2 == NULL) return 0;
223         // Do it
224         co->rightClick(co2);
225         return 0;
226 }
227
228 // set_hp(self, hp)
229 // hp = number of hitpoints (2 * number of hearts)
230 // returns: nil
231 int ObjectRef::l_set_hp(lua_State *L)
232 {
233         NO_MAP_LOCK_REQUIRED;
234         ObjectRef *ref = checkobject(L, 1);
235         luaL_checknumber(L, 2);
236         ServerActiveObject *co = getobject(ref);
237         if(co == NULL) return 0;
238         int hp = lua_tonumber(L, 2);
239         /*infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
240                         <<" hp="<<hp<<std::endl;*/
241         // Do it
242         co->setHP(hp);
243         // Return
244         return 0;
245 }
246
247 // get_hp(self)
248 // returns: number of hitpoints (2 * number of hearts)
249 // 0 if not applicable to this type of object
250 int ObjectRef::l_get_hp(lua_State *L)
251 {
252         NO_MAP_LOCK_REQUIRED;
253         ObjectRef *ref = checkobject(L, 1);
254         ServerActiveObject *co = getobject(ref);
255         if(co == NULL){
256                 // Default hp is 1
257                 lua_pushnumber(L, 1);
258                 return 1;
259         }
260         int hp = co->getHP();
261         /*infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
262                         <<" hp="<<hp<<std::endl;*/
263         // Return
264         lua_pushnumber(L, hp);
265         return 1;
266 }
267
268 // get_inventory(self)
269 int ObjectRef::l_get_inventory(lua_State *L)
270 {
271         NO_MAP_LOCK_REQUIRED;
272         ObjectRef *ref = checkobject(L, 1);
273         ServerActiveObject *co = getobject(ref);
274         if(co == NULL) return 0;
275         // Do it
276         InventoryLocation loc = co->getInventoryLocation();
277         if(getServer(L)->getInventory(loc) != NULL)
278                 InvRef::create(L, loc);
279         else
280                 lua_pushnil(L); // An object may have no inventory (nil)
281         return 1;
282 }
283
284 // get_wield_list(self)
285 int ObjectRef::l_get_wield_list(lua_State *L)
286 {
287         NO_MAP_LOCK_REQUIRED;
288         ObjectRef *ref = checkobject(L, 1);
289         ServerActiveObject *co = getobject(ref);
290         if(co == NULL) return 0;
291         // Do it
292         lua_pushstring(L, co->getWieldList().c_str());
293         return 1;
294 }
295
296 // get_wield_index(self)
297 int ObjectRef::l_get_wield_index(lua_State *L)
298 {
299         NO_MAP_LOCK_REQUIRED;
300         ObjectRef *ref = checkobject(L, 1);
301         ServerActiveObject *co = getobject(ref);
302         if(co == NULL) return 0;
303         // Do it
304         lua_pushinteger(L, co->getWieldIndex() + 1);
305         return 1;
306 }
307
308 // get_wielded_item(self)
309 int ObjectRef::l_get_wielded_item(lua_State *L)
310 {
311         NO_MAP_LOCK_REQUIRED;
312         ObjectRef *ref = checkobject(L, 1);
313         ServerActiveObject *co = getobject(ref);
314         if(co == NULL){
315                 // Empty ItemStack
316                 LuaItemStack::create(L, ItemStack());
317                 return 1;
318         }
319         // Do it
320         LuaItemStack::create(L, co->getWieldedItem());
321         return 1;
322 }
323
324 // set_wielded_item(self, itemstack or itemstring or table or nil)
325 int ObjectRef::l_set_wielded_item(lua_State *L)
326 {
327         NO_MAP_LOCK_REQUIRED;
328         ObjectRef *ref = checkobject(L, 1);
329         ServerActiveObject *co = getobject(ref);
330         if(co == NULL) return 0;
331         // Do it
332         ItemStack item = read_item(L, 2, getServer(L));
333         bool success = co->setWieldedItem(item);
334         lua_pushboolean(L, success);
335         return 1;
336 }
337
338 // set_armor_groups(self, groups)
339 int ObjectRef::l_set_armor_groups(lua_State *L)
340 {
341         NO_MAP_LOCK_REQUIRED;
342         ObjectRef *ref = checkobject(L, 1);
343         ServerActiveObject *co = getobject(ref);
344         if(co == NULL) return 0;
345         // Do it
346         ItemGroupList groups;
347         read_groups(L, 2, groups);
348         co->setArmorGroups(groups);
349         return 0;
350 }
351
352 // set_physics_override(self, physics_override_speed, physics_override_jump, physics_override_gravity)
353 int ObjectRef::l_set_physics_override(lua_State *L)
354 {
355         ObjectRef *ref = checkobject(L, 1);
356         PlayerSAO *co = (PlayerSAO *) getobject(ref);
357         if(co == NULL) return 0;
358         // Do it
359         if(!lua_isnil(L, 2)){
360                 co->m_physics_override_speed = lua_tonumber(L, 2);
361                 co->m_physics_override_sent = false;
362         }
363         if(!lua_isnil(L, 3)){
364                 co->m_physics_override_jump = lua_tonumber(L, 3);
365                 co->m_physics_override_sent = false;
366         }
367         if(!lua_isnil(L, 4)){
368                 co->m_physics_override_gravity = lua_tonumber(L, 4);
369                 co->m_physics_override_sent = false;
370         }
371         return 0;
372 }
373
374 // set_animation(self, frame_range, frame_speed, frame_blend)
375 int ObjectRef::l_set_animation(lua_State *L)
376 {
377         NO_MAP_LOCK_REQUIRED;
378         ObjectRef *ref = checkobject(L, 1);
379         ServerActiveObject *co = getobject(ref);
380         if(co == NULL) return 0;
381         // Do it
382         v2f frames = v2f(1, 1);
383         if(!lua_isnil(L, 2))
384                 frames = read_v2f(L, 2);
385         float frame_speed = 15;
386         if(!lua_isnil(L, 3))
387                 frame_speed = lua_tonumber(L, 3);
388         float frame_blend = 0;
389         if(!lua_isnil(L, 4))
390                 frame_blend = lua_tonumber(L, 4);
391         co->setAnimation(frames, frame_speed, frame_blend);
392         return 0;
393 }
394
395 // set_bone_position(self, std::string bone, v3f position, v3f rotation)
396 int ObjectRef::l_set_bone_position(lua_State *L)
397 {
398         NO_MAP_LOCK_REQUIRED;
399         ObjectRef *ref = checkobject(L, 1);
400         ServerActiveObject *co = getobject(ref);
401         if(co == NULL) return 0;
402         // Do it
403         std::string bone = "";
404         if(!lua_isnil(L, 2))
405                 bone = lua_tostring(L, 2);
406         v3f position = v3f(0, 0, 0);
407         if(!lua_isnil(L, 3))
408                 position = read_v3f(L, 3);
409         v3f rotation = v3f(0, 0, 0);
410         if(!lua_isnil(L, 4))
411                 rotation = read_v3f(L, 4);
412         co->setBonePosition(bone, position, rotation);
413         return 0;
414 }
415
416 // set_attach(self, parent, bone, position, rotation)
417 int ObjectRef::l_set_attach(lua_State *L)
418 {
419         NO_MAP_LOCK_REQUIRED;
420         ObjectRef *ref = checkobject(L, 1);
421         ObjectRef *parent_ref = checkobject(L, 2);
422         ServerActiveObject *co = getobject(ref);
423         ServerActiveObject *parent = getobject(parent_ref);
424         if(co == NULL) return 0;
425         if(parent == NULL) return 0;
426         // Do it
427         std::string bone = "";
428         if(!lua_isnil(L, 3))
429                 bone = lua_tostring(L, 3);
430         v3f position = v3f(0, 0, 0);
431         if(!lua_isnil(L, 4))
432                 position = read_v3f(L, 4);
433         v3f rotation = v3f(0, 0, 0);
434         if(!lua_isnil(L, 5))
435                 rotation = read_v3f(L, 5);
436         co->setAttachment(parent->getId(), bone, position, rotation);
437         return 0;
438 }
439
440 // set_detach(self)
441 int ObjectRef::l_set_detach(lua_State *L)
442 {
443         NO_MAP_LOCK_REQUIRED;
444         ObjectRef *ref = checkobject(L, 1);
445         ServerActiveObject *co = getobject(ref);
446         if(co == NULL) return 0;
447         // Do it
448         co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0));
449         return 0;
450 }
451
452 // set_properties(self, properties)
453 int ObjectRef::l_set_properties(lua_State *L)
454 {
455         NO_MAP_LOCK_REQUIRED;
456         ObjectRef *ref = checkobject(L, 1);
457         ServerActiveObject *co = getobject(ref);
458         if(co == NULL) return 0;
459         ObjectProperties *prop = co->accessObjectProperties();
460         if(!prop)
461                 return 0;
462         read_object_properties(L, 2, prop);
463         co->notifyObjectPropertiesModified();
464         return 0;
465 }
466
467 /* LuaEntitySAO-only */
468
469 // setvelocity(self, {x=num, y=num, z=num})
470 int ObjectRef::l_setvelocity(lua_State *L)
471 {
472         NO_MAP_LOCK_REQUIRED;
473         ObjectRef *ref = checkobject(L, 1);
474         LuaEntitySAO *co = getluaobject(ref);
475         if(co == NULL) return 0;
476         v3f pos = checkFloatPos(L, 2);
477         // Do it
478         co->setVelocity(pos);
479         return 0;
480 }
481
482 // getvelocity(self)
483 int ObjectRef::l_getvelocity(lua_State *L)
484 {
485         NO_MAP_LOCK_REQUIRED;
486         ObjectRef *ref = checkobject(L, 1);
487         LuaEntitySAO *co = getluaobject(ref);
488         if(co == NULL) return 0;
489         // Do it
490         v3f v = co->getVelocity();
491         pushFloatPos(L, v);
492         return 1;
493 }
494
495 // setacceleration(self, {x=num, y=num, z=num})
496 int ObjectRef::l_setacceleration(lua_State *L)
497 {
498         NO_MAP_LOCK_REQUIRED;
499         ObjectRef *ref = checkobject(L, 1);
500         LuaEntitySAO *co = getluaobject(ref);
501         if(co == NULL) return 0;
502         // pos
503         v3f pos = checkFloatPos(L, 2);
504         // Do it
505         co->setAcceleration(pos);
506         return 0;
507 }
508
509 // getacceleration(self)
510 int ObjectRef::l_getacceleration(lua_State *L)
511 {
512         NO_MAP_LOCK_REQUIRED;
513         ObjectRef *ref = checkobject(L, 1);
514         LuaEntitySAO *co = getluaobject(ref);
515         if(co == NULL) return 0;
516         // Do it
517         v3f v = co->getAcceleration();
518         pushFloatPos(L, v);
519         return 1;
520 }
521
522 // setyaw(self, radians)
523 int ObjectRef::l_setyaw(lua_State *L)
524 {
525         NO_MAP_LOCK_REQUIRED;
526         ObjectRef *ref = checkobject(L, 1);
527         LuaEntitySAO *co = getluaobject(ref);
528         if(co == NULL) return 0;
529         float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
530         // Do it
531         co->setYaw(yaw);
532         return 0;
533 }
534
535 // getyaw(self)
536 int ObjectRef::l_getyaw(lua_State *L)
537 {
538         NO_MAP_LOCK_REQUIRED;
539         ObjectRef *ref = checkobject(L, 1);
540         LuaEntitySAO *co = getluaobject(ref);
541         if(co == NULL) return 0;
542         // Do it
543         float yaw = co->getYaw() * core::DEGTORAD;
544         lua_pushnumber(L, yaw);
545         return 1;
546 }
547
548 // settexturemod(self, mod)
549 int ObjectRef::l_settexturemod(lua_State *L)
550 {
551         NO_MAP_LOCK_REQUIRED;
552         ObjectRef *ref = checkobject(L, 1);
553         LuaEntitySAO *co = getluaobject(ref);
554         if(co == NULL) return 0;
555         // Do it
556         std::string mod = luaL_checkstring(L, 2);
557         co->setTextureMod(mod);
558         return 0;
559 }
560
561 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
562 //           select_horiz_by_yawpitch=false)
563 int ObjectRef::l_setsprite(lua_State *L)
564 {
565         NO_MAP_LOCK_REQUIRED;
566         ObjectRef *ref = checkobject(L, 1);
567         LuaEntitySAO *co = getluaobject(ref);
568         if(co == NULL) return 0;
569         // Do it
570         v2s16 p(0,0);
571         if(!lua_isnil(L, 2))
572                 p = read_v2s16(L, 2);
573         int num_frames = 1;
574         if(!lua_isnil(L, 3))
575                 num_frames = lua_tonumber(L, 3);
576         float framelength = 0.2;
577         if(!lua_isnil(L, 4))
578                 framelength = lua_tonumber(L, 4);
579         bool select_horiz_by_yawpitch = false;
580         if(!lua_isnil(L, 5))
581                 select_horiz_by_yawpitch = lua_toboolean(L, 5);
582         co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
583         return 0;
584 }
585
586 // DEPRECATED
587 // get_entity_name(self)
588 int ObjectRef::l_get_entity_name(lua_State *L)
589 {
590         NO_MAP_LOCK_REQUIRED;
591         ObjectRef *ref = checkobject(L, 1);
592         LuaEntitySAO *co = getluaobject(ref);
593         if(co == NULL) return 0;
594         // Do it
595         std::string name = co->getName();
596         lua_pushstring(L, name.c_str());
597         return 1;
598 }
599
600 // get_luaentity(self)
601 int ObjectRef::l_get_luaentity(lua_State *L)
602 {
603         NO_MAP_LOCK_REQUIRED;
604         ObjectRef *ref = checkobject(L, 1);
605         LuaEntitySAO *co = getluaobject(ref);
606         if(co == NULL) return 0;
607         // Do it
608         luaentity_get(L, co->getId());
609         return 1;
610 }
611
612 /* Player-only */
613
614 // is_player(self)
615 int ObjectRef::l_is_player(lua_State *L)
616 {
617         NO_MAP_LOCK_REQUIRED;
618         ObjectRef *ref = checkobject(L, 1);
619         Player *player = getplayer(ref);
620         lua_pushboolean(L, (player != NULL));
621         return 1;
622 }
623
624 // get_player_name(self)
625 int ObjectRef::l_get_player_name(lua_State *L)
626 {
627         NO_MAP_LOCK_REQUIRED;
628         ObjectRef *ref = checkobject(L, 1);
629         Player *player = getplayer(ref);
630         if(player == NULL){
631                 lua_pushlstring(L, "", 0);
632                 return 1;
633         }
634         // Do it
635         lua_pushstring(L, player->getName());
636         return 1;
637 }
638
639 // get_look_dir(self)
640 int ObjectRef::l_get_look_dir(lua_State *L)
641 {
642         NO_MAP_LOCK_REQUIRED;
643         ObjectRef *ref = checkobject(L, 1);
644         Player *player = getplayer(ref);
645         if(player == NULL) return 0;
646         // Do it
647         float pitch = player->getRadPitch();
648         float yaw = player->getRadYaw();
649         v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw));
650         push_v3f(L, v);
651         return 1;
652 }
653
654 // get_look_pitch(self)
655 int ObjectRef::l_get_look_pitch(lua_State *L)
656 {
657         NO_MAP_LOCK_REQUIRED;
658         ObjectRef *ref = checkobject(L, 1);
659         Player *player = getplayer(ref);
660         if(player == NULL) return 0;
661         // Do it
662         lua_pushnumber(L, player->getRadPitch());
663         return 1;
664 }
665
666 // get_look_yaw(self)
667 int ObjectRef::l_get_look_yaw(lua_State *L)
668 {
669         NO_MAP_LOCK_REQUIRED;
670         ObjectRef *ref = checkobject(L, 1);
671         Player *player = getplayer(ref);
672         if(player == NULL) return 0;
673         // Do it
674         lua_pushnumber(L, player->getRadYaw());
675         return 1;
676 }
677
678 // set_look_pitch(self, radians)
679 int ObjectRef::l_set_look_pitch(lua_State *L)
680 {
681         NO_MAP_LOCK_REQUIRED;
682         ObjectRef *ref = checkobject(L, 1);
683         PlayerSAO* co = getplayersao(ref);
684         if(co == NULL) return 0;
685         float pitch = luaL_checknumber(L, 2) * core::RADTODEG;
686         // Do it
687         co->setPitch(pitch);
688         return 1;
689 }
690
691 // set_look_yaw(self, radians)
692 int ObjectRef::l_set_look_yaw(lua_State *L)
693 {
694         NO_MAP_LOCK_REQUIRED;
695         ObjectRef *ref = checkobject(L, 1);
696         PlayerSAO* co = getplayersao(ref);
697         if(co == NULL) return 0;
698         float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
699         // Do it
700         co->setYaw(yaw);
701         return 1;
702 }
703
704 // set_breath(self, breath)
705 int ObjectRef::l_set_breath(lua_State *L)
706 {
707         NO_MAP_LOCK_REQUIRED;
708         ObjectRef *ref = checkobject(L, 1);
709         PlayerSAO* co = getplayersao(ref);
710         if(co == NULL) return 0;
711         u16 breath = luaL_checknumber(L, 2);
712         // Do it
713         co->setBreath(breath);
714         co->m_breath_not_sent = true;
715         return 0;
716 }
717
718 // get_breath(self)
719 int ObjectRef::l_get_breath(lua_State *L)
720 {
721         NO_MAP_LOCK_REQUIRED;
722         ObjectRef *ref = checkobject(L, 1);
723         PlayerSAO* co = getplayersao(ref);
724         if(co == NULL) return 0;
725         // Do it
726         u16 breath = co->getBreath();
727         lua_pushinteger (L, breath);
728         return 1;
729 }
730
731 // set_inventory_formspec(self, formspec)
732 int ObjectRef::l_set_inventory_formspec(lua_State *L)
733 {
734         NO_MAP_LOCK_REQUIRED;
735         ObjectRef *ref = checkobject(L, 1);
736         Player *player = getplayer(ref);
737         if(player == NULL) return 0;
738         std::string formspec = luaL_checkstring(L, 2);
739
740         player->inventory_formspec = formspec;
741         getServer(L)->reportInventoryFormspecModified(player->getName());
742         lua_pushboolean(L, true);
743         return 1;
744 }
745
746 // get_inventory_formspec(self) -> formspec
747 int ObjectRef::l_get_inventory_formspec(lua_State *L)
748 {
749         NO_MAP_LOCK_REQUIRED;
750         ObjectRef *ref = checkobject(L, 1);
751         Player *player = getplayer(ref);
752         if(player == NULL) return 0;
753
754         std::string formspec = player->inventory_formspec;
755         lua_pushlstring(L, formspec.c_str(), formspec.size());
756         return 1;
757 }
758
759 // get_player_control(self)
760 int ObjectRef::l_get_player_control(lua_State *L)
761 {
762         NO_MAP_LOCK_REQUIRED;
763         ObjectRef *ref = checkobject(L, 1);
764         Player *player = getplayer(ref);
765         if(player == NULL){
766                 lua_pushlstring(L, "", 0);
767                 return 1;
768         }
769         // Do it
770         PlayerControl control = player->getPlayerControl();
771         lua_newtable(L);
772         lua_pushboolean(L, control.up);
773         lua_setfield(L, -2, "up");
774         lua_pushboolean(L, control.down);
775         lua_setfield(L, -2, "down");
776         lua_pushboolean(L, control.left);
777         lua_setfield(L, -2, "left");
778         lua_pushboolean(L, control.right);
779         lua_setfield(L, -2, "right");
780         lua_pushboolean(L, control.jump);
781         lua_setfield(L, -2, "jump");
782         lua_pushboolean(L, control.aux1);
783         lua_setfield(L, -2, "aux1");
784         lua_pushboolean(L, control.sneak);
785         lua_setfield(L, -2, "sneak");
786         lua_pushboolean(L, control.LMB);
787         lua_setfield(L, -2, "LMB");
788         lua_pushboolean(L, control.RMB);
789         lua_setfield(L, -2, "RMB");
790         return 1;
791 }
792
793 // get_player_control_bits(self)
794 int ObjectRef::l_get_player_control_bits(lua_State *L)
795 {
796         NO_MAP_LOCK_REQUIRED;
797         ObjectRef *ref = checkobject(L, 1);
798         Player *player = getplayer(ref);
799         if(player == NULL){
800                 lua_pushlstring(L, "", 0);
801                 return 1;
802         }
803         // Do it
804         lua_pushnumber(L, player->keyPressed);
805         return 1;
806 }
807
808 // hud_add(self, form)
809 int ObjectRef::l_hud_add(lua_State *L)
810 {
811         ObjectRef *ref = checkobject(L, 1);
812         Player *player = getplayer(ref);
813         if (player == NULL)
814                 return 0;
815
816         HudElement *elem = new HudElement;
817
818         elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type",
819                                                                 es_HudElementType, HUD_ELEM_TEXT);
820
821         lua_getfield(L, 2, "position");
822         elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
823         lua_pop(L, 1);
824
825         lua_getfield(L, 2, "scale");
826         elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
827         lua_pop(L, 1);
828
829         elem->name   = getstringfield_default(L, 2, "name", "");
830         elem->text   = getstringfield_default(L, 2, "text", "");
831         elem->number = getintfield_default(L, 2, "number", 0);
832         elem->item   = getintfield_default(L, 2, "item", 0);
833         elem->dir    = getintfield_default(L, 2, "dir", 0);
834
835         lua_getfield(L, 2, "alignment");
836         elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
837         lua_pop(L, 1);
838
839         lua_getfield(L, 2, "offset");
840         elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
841         lua_pop(L, 1);
842
843         u32 id = getServer(L)->hudAdd(player, elem);
844         if (id == (u32)-1) {
845                 delete elem;
846                 return 0;
847         }
848
849         lua_pushnumber(L, id);
850         return 1;
851 }
852
853 // hud_remove(self, id)
854 int ObjectRef::l_hud_remove(lua_State *L)
855 {
856         ObjectRef *ref = checkobject(L, 1);
857         Player *player = getplayer(ref);
858         if (player == NULL)
859                 return 0;
860
861         u32 id = -1;
862         if (!lua_isnil(L, 2))
863                 id = lua_tonumber(L, 2);
864
865         if (!getServer(L)->hudRemove(player, id))
866                 return 0;
867
868         lua_pushboolean(L, true);
869         return 1;
870 }
871
872 // hud_change(self, id, stat, data)
873 int ObjectRef::l_hud_change(lua_State *L)
874 {
875         ObjectRef *ref = checkobject(L, 1);
876         Player *player = getplayer(ref);
877         if (player == NULL)
878                 return 0;
879
880         u32 id = -1;
881         if (!lua_isnil(L, 2))
882                 id = lua_tonumber(L, 2);
883
884         HudElementStat stat = (HudElementStat)getenumfield(L, 3, "stat",
885                                                                 es_HudElementStat, HUD_STAT_NUMBER);
886
887         if (id >= player->hud.size())
888                 return 0;
889
890         void *value = NULL;
891         HudElement *e = player->hud[id];
892         if (!e)
893                 return 0;
894
895         switch (stat) {
896                 case HUD_STAT_POS:
897                         e->pos = read_v2f(L, 4);
898                         value = &e->pos;
899                         break;
900                 case HUD_STAT_NAME:
901                         e->name = lua_tostring(L, 4);
902                         value = &e->name;
903                         break;
904                 case HUD_STAT_SCALE:
905                         e->scale = read_v2f(L, 4);
906                         value = &e->scale;
907                         break;
908                 case HUD_STAT_TEXT:
909                         e->text = lua_tostring(L, 4);
910                         value = &e->text;
911                         break;
912                 case HUD_STAT_NUMBER:
913                         e->number = lua_tonumber(L, 4);
914                         value = &e->number;
915                         break;
916                 case HUD_STAT_ITEM:
917                         e->item = lua_tonumber(L, 4);
918                         value = &e->item;
919                         break;
920                 case HUD_STAT_DIR:
921                         e->dir = lua_tonumber(L, 4);
922                         value = &e->dir;
923                 case HUD_STAT_ALIGN:
924                         e->align = read_v2f(L, 4);
925                         value = &e->align;
926                 case HUD_STAT_OFFSET:
927                         e->offset = read_v2f(L, 4);
928                         value = &e->offset;
929         }
930
931         getServer(L)->hudChange(player, id, stat, value);
932
933         lua_pushboolean(L, true);
934         return 1;
935 }
936
937 // hud_get(self, id)
938 int ObjectRef::l_hud_get(lua_State *L)
939 {
940         ObjectRef *ref = checkobject(L, 1);
941         Player *player = getplayer(ref);
942         if (player == NULL)
943                 return 0;
944
945         u32 id = lua_tonumber(L, -1);
946         if (id >= player->hud.size())
947                 return 0;
948
949         HudElement *e = player->hud[id];
950         if (!e)
951                 return 0;
952
953         lua_newtable(L);
954
955         lua_pushstring(L, es_HudElementType[(u8)e->type].str);
956         lua_setfield(L, -2, "type");
957
958         push_v2f(L, e->pos);
959         lua_setfield(L, -2, "position");
960
961         lua_pushstring(L, e->name.c_str());
962         lua_setfield(L, -2, "name");
963
964         push_v2f(L, e->scale);
965         lua_setfield(L, -2, "scale");
966
967         lua_pushstring(L, e->text.c_str());
968         lua_setfield(L, -2, "text");
969
970         lua_pushnumber(L, e->number);
971         lua_setfield(L, -2, "number");
972
973         lua_pushnumber(L, e->item);
974         lua_setfield(L, -2, "item");
975
976         lua_pushnumber(L, e->dir);
977         lua_setfield(L, -2, "dir");
978
979         return 1;
980 }
981
982 // hud_set_flags(self, flags)
983 int ObjectRef::l_hud_set_flags(lua_State *L)
984 {
985         ObjectRef *ref = checkobject(L, 1);
986         Player *player = getplayer(ref);
987         if (player == NULL)
988                 return 0;
989
990         u32 flags = 0;
991         u32 mask  = 0;
992         bool flag;
993         
994         const EnumString *esp = es_HudBuiltinElement;
995         for (int i = 0; esp[i].str; i++) {
996                 if (getboolfield(L, 2, esp[i].str, flag)) {
997                         flags |= esp[i].num * flag;
998                         mask  |= esp[i].num;
999                 }
1000         }
1001         if (!getServer(L)->hudSetFlags(player, flags, mask))
1002                 return 0;
1003
1004         lua_pushboolean(L, true);
1005         return 1;
1006 }
1007
1008 // hud_set_hotbar_itemcount(self, hotbar_itemcount)
1009 int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
1010 {
1011         ObjectRef *ref = checkobject(L, 1);
1012         Player *player = getplayer(ref);
1013         if (player == NULL)
1014                 return 0;
1015
1016         s32 hotbar_itemcount = lua_tonumber(L, 2);
1017
1018         if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
1019                 return 0;
1020
1021         lua_pushboolean(L, true);
1022         return 1;
1023 }
1024
1025 ObjectRef::ObjectRef(ServerActiveObject *object):
1026         m_object(object)
1027 {
1028         //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
1029 }
1030
1031 ObjectRef::~ObjectRef()
1032 {
1033         /*if(m_object)
1034                 infostream<<"ObjectRef destructing for id="
1035                                 <<m_object->getId()<<std::endl;
1036         else
1037                 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
1038 }
1039
1040 // Creates an ObjectRef and leaves it on top of stack
1041 // Not callable from Lua; all references are created on the C side.
1042 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
1043 {
1044         ObjectRef *o = new ObjectRef(object);
1045         //infostream<<"ObjectRef::create: o="<<o<<std::endl;
1046         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1047         luaL_getmetatable(L, className);
1048         lua_setmetatable(L, -2);
1049 }
1050
1051 void ObjectRef::set_null(lua_State *L)
1052 {
1053         ObjectRef *o = checkobject(L, -1);
1054         o->m_object = NULL;
1055 }
1056
1057 void ObjectRef::Register(lua_State *L)
1058 {
1059         lua_newtable(L);
1060         int methodtable = lua_gettop(L);
1061         luaL_newmetatable(L, className);
1062         int metatable = lua_gettop(L);
1063
1064         lua_pushliteral(L, "__metatable");
1065         lua_pushvalue(L, methodtable);
1066         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
1067
1068         lua_pushliteral(L, "__index");
1069         lua_pushvalue(L, methodtable);
1070         lua_settable(L, metatable);
1071
1072         lua_pushliteral(L, "__gc");
1073         lua_pushcfunction(L, gc_object);
1074         lua_settable(L, metatable);
1075
1076         lua_pop(L, 1);  // drop metatable
1077
1078         luaL_openlib(L, 0, methods, 0);  // fill methodtable
1079         lua_pop(L, 1);  // drop methodtable
1080
1081         // Cannot be created from Lua
1082         //lua_register(L, className, create_object);
1083 }
1084
1085 const char ObjectRef::className[] = "ObjectRef";
1086 const luaL_reg ObjectRef::methods[] = {
1087         // ServerActiveObject
1088         luamethod(ObjectRef, remove),
1089         luamethod(ObjectRef, getpos),
1090         luamethod(ObjectRef, setpos),
1091         luamethod(ObjectRef, moveto),
1092         luamethod(ObjectRef, punch),
1093         luamethod(ObjectRef, right_click),
1094         luamethod(ObjectRef, set_hp),
1095         luamethod(ObjectRef, get_hp),
1096         luamethod(ObjectRef, get_inventory),
1097         luamethod(ObjectRef, get_wield_list),
1098         luamethod(ObjectRef, get_wield_index),
1099         luamethod(ObjectRef, get_wielded_item),
1100         luamethod(ObjectRef, set_wielded_item),
1101         luamethod(ObjectRef, set_armor_groups),
1102         luamethod(ObjectRef, set_physics_override),
1103         luamethod(ObjectRef, set_animation),
1104         luamethod(ObjectRef, set_bone_position),
1105         luamethod(ObjectRef, set_attach),
1106         luamethod(ObjectRef, set_detach),
1107         luamethod(ObjectRef, set_properties),
1108         // LuaEntitySAO-only
1109         luamethod(ObjectRef, setvelocity),
1110         luamethod(ObjectRef, getvelocity),
1111         luamethod(ObjectRef, setacceleration),
1112         luamethod(ObjectRef, getacceleration),
1113         luamethod(ObjectRef, setyaw),
1114         luamethod(ObjectRef, getyaw),
1115         luamethod(ObjectRef, settexturemod),
1116         luamethod(ObjectRef, setsprite),
1117         luamethod(ObjectRef, get_entity_name),
1118         luamethod(ObjectRef, get_luaentity),
1119         // Player-only
1120         luamethod(ObjectRef, is_player),
1121         luamethod(ObjectRef, get_player_name),
1122         luamethod(ObjectRef, get_look_dir),
1123         luamethod(ObjectRef, get_look_pitch),
1124         luamethod(ObjectRef, get_look_yaw),
1125         luamethod(ObjectRef, set_look_yaw),
1126         luamethod(ObjectRef, set_look_pitch),
1127         luamethod(ObjectRef, get_breath),
1128         luamethod(ObjectRef, set_breath),
1129         luamethod(ObjectRef, set_inventory_formspec),
1130         luamethod(ObjectRef, get_inventory_formspec),
1131         luamethod(ObjectRef, get_player_control),
1132         luamethod(ObjectRef, get_player_control_bits),
1133         luamethod(ObjectRef, hud_add),
1134         luamethod(ObjectRef, hud_remove),
1135         luamethod(ObjectRef, hud_change),
1136         luamethod(ObjectRef, hud_get),
1137         luamethod(ObjectRef, hud_set_flags),
1138         luamethod(ObjectRef, hud_set_hotbar_itemcount),
1139         {0,0}
1140 };