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