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