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