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