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