]> git.lizzy.rs Git - minetest.git/blob - src/scriptapi_object.cpp
Merge remote branch 'origin/master'
[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
704 ObjectRef::ObjectRef(ServerActiveObject *object):
705         m_object(object)
706 {
707         //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
708 }
709
710 ObjectRef::~ObjectRef()
711 {
712         /*if(m_object)
713                 infostream<<"ObjectRef destructing for id="
714                                 <<m_object->getId()<<std::endl;
715         else
716                 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
717 }
718
719 // Creates an ObjectRef and leaves it on top of stack
720 // Not callable from Lua; all references are created on the C side.
721 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
722 {
723         ObjectRef *o = new ObjectRef(object);
724         //infostream<<"ObjectRef::create: o="<<o<<std::endl;
725         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
726         luaL_getmetatable(L, className);
727         lua_setmetatable(L, -2);
728 }
729
730 void ObjectRef::set_null(lua_State *L)
731 {
732         ObjectRef *o = checkobject(L, -1);
733         o->m_object = NULL;
734 }
735
736 void ObjectRef::Register(lua_State *L)
737 {
738         lua_newtable(L);
739         int methodtable = lua_gettop(L);
740         luaL_newmetatable(L, className);
741         int metatable = lua_gettop(L);
742
743         lua_pushliteral(L, "__metatable");
744         lua_pushvalue(L, methodtable);
745         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
746
747         lua_pushliteral(L, "__index");
748         lua_pushvalue(L, methodtable);
749         lua_settable(L, metatable);
750
751         lua_pushliteral(L, "__gc");
752         lua_pushcfunction(L, gc_object);
753         lua_settable(L, metatable);
754
755         lua_pop(L, 1);  // drop metatable
756
757         luaL_openlib(L, 0, methods, 0);  // fill methodtable
758         lua_pop(L, 1);  // drop methodtable
759
760         // Cannot be created from Lua
761         //lua_register(L, className, create_object);
762 }
763
764 const char ObjectRef::className[] = "ObjectRef";
765 const luaL_reg ObjectRef::methods[] = {
766         // ServerActiveObject
767         luamethod(ObjectRef, remove),
768         luamethod(ObjectRef, getpos),
769         luamethod(ObjectRef, setpos),
770         luamethod(ObjectRef, moveto),
771         luamethod(ObjectRef, punch),
772         luamethod(ObjectRef, right_click),
773         luamethod(ObjectRef, set_hp),
774         luamethod(ObjectRef, get_hp),
775         luamethod(ObjectRef, get_inventory),
776         luamethod(ObjectRef, get_wield_list),
777         luamethod(ObjectRef, get_wield_index),
778         luamethod(ObjectRef, get_wielded_item),
779         luamethod(ObjectRef, set_wielded_item),
780         luamethod(ObjectRef, set_armor_groups),
781         luamethod(ObjectRef, set_physics_override),
782         luamethod(ObjectRef, set_animation),
783         luamethod(ObjectRef, set_bone_position),
784         luamethod(ObjectRef, set_attach),
785         luamethod(ObjectRef, set_detach),
786         luamethod(ObjectRef, set_properties),
787         // LuaEntitySAO-only
788         luamethod(ObjectRef, setvelocity),
789         luamethod(ObjectRef, getvelocity),
790         luamethod(ObjectRef, setacceleration),
791         luamethod(ObjectRef, getacceleration),
792         luamethod(ObjectRef, setyaw),
793         luamethod(ObjectRef, getyaw),
794         luamethod(ObjectRef, settexturemod),
795         luamethod(ObjectRef, setsprite),
796         luamethod(ObjectRef, get_entity_name),
797         luamethod(ObjectRef, get_luaentity),
798         // Player-only
799         luamethod(ObjectRef, is_player),
800         luamethod(ObjectRef, get_player_name),
801         luamethod(ObjectRef, get_look_dir),
802         luamethod(ObjectRef, get_look_pitch),
803         luamethod(ObjectRef, get_look_yaw),
804         luamethod(ObjectRef, set_look_yaw),
805         luamethod(ObjectRef, set_look_pitch),
806         luamethod(ObjectRef, set_inventory_formspec),
807         luamethod(ObjectRef, get_inventory_formspec),
808         luamethod(ObjectRef, get_player_control),
809         luamethod(ObjectRef, get_player_control_bits),
810         {0,0}
811 };
812
813 // Creates a new anonymous reference if cobj=NULL or id=0
814 void objectref_get_or_create(lua_State *L,
815                 ServerActiveObject *cobj)
816 {
817         if(cobj == NULL || cobj->getId() == 0){
818                 ObjectRef::create(L, cobj);
819         } else {
820                 objectref_get(L, cobj->getId());
821         }
822 }
823
824 void objectref_get(lua_State *L, u16 id)
825 {
826         // Get minetest.object_refs[i]
827         lua_getglobal(L, "minetest");
828         lua_getfield(L, -1, "object_refs");
829         luaL_checktype(L, -1, LUA_TTABLE);
830         lua_pushnumber(L, id);
831         lua_gettable(L, -2);
832         lua_remove(L, -2); // object_refs
833         lua_remove(L, -2); // minetest
834 }
835
836 /*
837         ObjectProperties
838 */
839
840 void read_object_properties(lua_State *L, int index,
841                 ObjectProperties *prop)
842 {
843         if(index < 0)
844                 index = lua_gettop(L) + 1 + index;
845         if(!lua_istable(L, index))
846                 return;
847
848         prop->hp_max = getintfield_default(L, -1, "hp_max", 10);
849
850         getboolfield(L, -1, "physical", prop->physical);
851
852         getfloatfield(L, -1, "weight", prop->weight);
853
854         lua_getfield(L, -1, "collisionbox");
855         if(lua_istable(L, -1))
856                 prop->collisionbox = read_aabb3f(L, -1, 1.0);
857         lua_pop(L, 1);
858
859         getstringfield(L, -1, "visual", prop->visual);
860
861         getstringfield(L, -1, "mesh", prop->mesh);
862
863         lua_getfield(L, -1, "visual_size");
864         if(lua_istable(L, -1))
865                 prop->visual_size = read_v2f(L, -1);
866         lua_pop(L, 1);
867
868         lua_getfield(L, -1, "textures");
869         if(lua_istable(L, -1)){
870                 prop->textures.clear();
871                 int table = lua_gettop(L);
872                 lua_pushnil(L);
873                 while(lua_next(L, table) != 0){
874                         // key at index -2 and value at index -1
875                         if(lua_isstring(L, -1))
876                                 prop->textures.push_back(lua_tostring(L, -1));
877                         else
878                                 prop->textures.push_back("");
879                         // removes value, keeps key for next iteration
880                         lua_pop(L, 1);
881                 }
882         }
883         lua_pop(L, 1);
884
885         lua_getfield(L, -1, "colors");
886         if(lua_istable(L, -1)){
887                 prop->colors.clear();
888                 int table = lua_gettop(L);
889                 lua_pushnil(L);
890                 while(lua_next(L, table) != 0){
891                         // key at index -2 and value at index -1
892                         if(lua_isstring(L, -1))
893                                 prop->colors.push_back(readARGB8(L, -1));
894                         else
895                                 prop->colors.push_back(video::SColor(255, 255, 255, 255));
896                         // removes value, keeps key for next iteration
897                         lua_pop(L, 1);
898                 }
899         }
900         lua_pop(L, 1);
901
902         lua_getfield(L, -1, "spritediv");
903         if(lua_istable(L, -1))
904                 prop->spritediv = read_v2s16(L, -1);
905         lua_pop(L, 1);
906
907         lua_getfield(L, -1, "initial_sprite_basepos");
908         if(lua_istable(L, -1))
909                 prop->initial_sprite_basepos = read_v2s16(L, -1);
910         lua_pop(L, 1);
911
912         getboolfield(L, -1, "is_visible", prop->is_visible);
913         getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound);
914         getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate);
915 }
916
917 /*
918         object_reference
919 */
920
921 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
922 {
923         realitycheck(L);
924         assert(lua_checkstack(L, 20));
925         //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
926         StackUnroller stack_unroller(L);
927
928         // Create object on stack
929         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
930         int object = lua_gettop(L);
931
932         // Get minetest.object_refs table
933         lua_getglobal(L, "minetest");
934         lua_getfield(L, -1, "object_refs");
935         luaL_checktype(L, -1, LUA_TTABLE);
936         int objectstable = lua_gettop(L);
937
938         // object_refs[id] = object
939         lua_pushnumber(L, cobj->getId()); // Push id
940         lua_pushvalue(L, object); // Copy object to top of stack
941         lua_settable(L, objectstable);
942 }
943
944 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
945 {
946         realitycheck(L);
947         assert(lua_checkstack(L, 20));
948         //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
949         StackUnroller stack_unroller(L);
950
951         // Get minetest.object_refs table
952         lua_getglobal(L, "minetest");
953         lua_getfield(L, -1, "object_refs");
954         luaL_checktype(L, -1, LUA_TTABLE);
955         int objectstable = lua_gettop(L);
956
957         // Get object_refs[id]
958         lua_pushnumber(L, cobj->getId()); // Push id
959         lua_gettable(L, objectstable);
960         // Set object reference to NULL
961         ObjectRef::set_null(L);
962         lua_pop(L, 1); // pop object
963
964         // Set object_refs[id] = nil
965         lua_pushnumber(L, cobj->getId()); // Push id
966         lua_pushnil(L);
967         lua_settable(L, objectstable);
968 }