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