Re-add jungles, apple trees
[oweals/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 /*
32         ObjectRef
33 */
34
35
36 ObjectRef* ObjectRef::checkobject(lua_State *L, int narg)
37 {
38         luaL_checktype(L, narg, LUA_TUSERDATA);
39         void *ud = luaL_checkudata(L, narg, className);
40         if(!ud) luaL_typerror(L, narg, className);
41         return *(ObjectRef**)ud;  // unbox pointer
42 }
43
44 ServerActiveObject* ObjectRef::getobject(ObjectRef *ref)
45 {
46         ServerActiveObject *co = ref->m_object;
47         return co;
48 }
49
50 LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
51 {
52         ServerActiveObject *obj = getobject(ref);
53         if(obj == NULL)
54                 return NULL;
55         if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
56                 return NULL;
57         return (LuaEntitySAO*)obj;
58 }
59
60 PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
61 {
62         ServerActiveObject *obj = getobject(ref);
63         if(obj == NULL)
64                 return NULL;
65         if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
66                 return NULL;
67         return (PlayerSAO*)obj;
68 }
69
70 Player* ObjectRef::getplayer(ObjectRef *ref)
71 {
72         PlayerSAO *playersao = getplayersao(ref);
73         if(playersao == NULL)
74                 return NULL;
75         return playersao->getPlayer();
76 }
77
78 // Exported functions
79
80 // garbage collector
81 int ObjectRef::gc_object(lua_State *L) {
82         ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
83         //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
84         delete o;
85         return 0;
86 }
87
88 // remove(self)
89 int ObjectRef::l_remove(lua_State *L)
90 {
91         ObjectRef *ref = checkobject(L, 1);
92         ServerActiveObject *co = getobject(ref);
93         if(co == NULL) return 0;
94         verbosestream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
95         co->m_removed = true;
96         return 0;
97 }
98
99 // getpos(self)
100 // returns: {x=num, y=num, z=num}
101 int ObjectRef::l_getpos(lua_State *L)
102 {
103         ObjectRef *ref = checkobject(L, 1);
104         ServerActiveObject *co = getobject(ref);
105         if(co == NULL) return 0;
106         v3f pos = co->getBasePosition() / BS;
107         lua_newtable(L);
108         lua_pushnumber(L, pos.X);
109         lua_setfield(L, -2, "x");
110         lua_pushnumber(L, pos.Y);
111         lua_setfield(L, -2, "y");
112         lua_pushnumber(L, pos.Z);
113         lua_setfield(L, -2, "z");
114         return 1;
115 }
116
117 // setpos(self, pos)
118 int ObjectRef::l_setpos(lua_State *L)
119 {
120         ObjectRef *ref = checkobject(L, 1);
121         //LuaEntitySAO *co = getluaobject(ref);
122         ServerActiveObject *co = getobject(ref);
123         if(co == NULL) return 0;
124         // pos
125         v3f pos = checkFloatPos(L, 2);
126         // Do it
127         co->setPos(pos);
128         return 0;
129 }
130
131 // moveto(self, pos, continuous=false)
132 int ObjectRef::l_moveto(lua_State *L)
133 {
134         ObjectRef *ref = checkobject(L, 1);
135         //LuaEntitySAO *co = getluaobject(ref);
136         ServerActiveObject *co = getobject(ref);
137         if(co == NULL) return 0;
138         // pos
139         v3f pos = checkFloatPos(L, 2);
140         // continuous
141         bool continuous = lua_toboolean(L, 3);
142         // Do it
143         co->moveTo(pos, continuous);
144         return 0;
145 }
146
147 // punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
148 int ObjectRef::l_punch(lua_State *L)
149 {
150         ObjectRef *ref = checkobject(L, 1);
151         ObjectRef *puncher_ref = checkobject(L, 2);
152         ServerActiveObject *co = getobject(ref);
153         ServerActiveObject *puncher = getobject(puncher_ref);
154         if(co == NULL) return 0;
155         if(puncher == NULL) return 0;
156         v3f dir;
157         if(lua_type(L, 5) != LUA_TTABLE)
158                 dir = co->getBasePosition() - puncher->getBasePosition();
159         else
160                 dir = read_v3f(L, 5);
161         float time_from_last_punch = 1000000;
162         if(lua_isnumber(L, 3))
163                 time_from_last_punch = lua_tonumber(L, 3);
164         ToolCapabilities toolcap = read_tool_capabilities(L, 4);
165         dir.normalize();
166         // Do it
167         co->punch(dir, &toolcap, puncher, time_from_last_punch);
168         return 0;
169 }
170
171 // right_click(self, clicker); clicker = an another ObjectRef
172 int ObjectRef::l_right_click(lua_State *L)
173 {
174         ObjectRef *ref = checkobject(L, 1);
175         ObjectRef *ref2 = checkobject(L, 2);
176         ServerActiveObject *co = getobject(ref);
177         ServerActiveObject *co2 = getobject(ref2);
178         if(co == NULL) return 0;
179         if(co2 == NULL) return 0;
180         // Do it
181         co->rightClick(co2);
182         return 0;
183 }
184
185 // set_hp(self, hp)
186 // hp = number of hitpoints (2 * number of hearts)
187 // returns: nil
188 int ObjectRef::l_set_hp(lua_State *L)
189 {
190         ObjectRef *ref = checkobject(L, 1);
191         luaL_checknumber(L, 2);
192         ServerActiveObject *co = getobject(ref);
193         if(co == NULL) return 0;
194         int hp = lua_tonumber(L, 2);
195         /*infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
196                         <<" hp="<<hp<<std::endl;*/
197         // Do it
198         co->setHP(hp);
199         // Return
200         return 0;
201 }
202
203 // get_hp(self)
204 // returns: number of hitpoints (2 * number of hearts)
205 // 0 if not applicable to this type of object
206 int ObjectRef::l_get_hp(lua_State *L)
207 {
208         ObjectRef *ref = checkobject(L, 1);
209         ServerActiveObject *co = getobject(ref);
210         if(co == NULL){
211                 // Default hp is 1
212                 lua_pushnumber(L, 1);
213                 return 1;
214         }
215         int hp = co->getHP();
216         /*infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
217                         <<" hp="<<hp<<std::endl;*/
218         // Return
219         lua_pushnumber(L, hp);
220         return 1;
221 }
222
223 // get_inventory(self)
224 int ObjectRef::l_get_inventory(lua_State *L)
225 {
226         ObjectRef *ref = checkobject(L, 1);
227         ServerActiveObject *co = getobject(ref);
228         if(co == NULL) return 0;
229         // Do it
230         InventoryLocation loc = co->getInventoryLocation();
231         if(get_server(L)->getInventory(loc) != NULL)
232                 InvRef::create(L, loc);
233         else
234                 lua_pushnil(L); // An object may have no inventory (nil)
235         return 1;
236 }
237
238 // get_wield_list(self)
239 int ObjectRef::l_get_wield_list(lua_State *L)
240 {
241         ObjectRef *ref = checkobject(L, 1);
242         ServerActiveObject *co = getobject(ref);
243         if(co == NULL) return 0;
244         // Do it
245         lua_pushstring(L, co->getWieldList().c_str());
246         return 1;
247 }
248
249 // get_wield_index(self)
250 int ObjectRef::l_get_wield_index(lua_State *L)
251 {
252         ObjectRef *ref = checkobject(L, 1);
253         ServerActiveObject *co = getobject(ref);
254         if(co == NULL) return 0;
255         // Do it
256         lua_pushinteger(L, co->getWieldIndex() + 1);
257         return 1;
258 }
259
260 // get_wielded_item(self)
261 int ObjectRef::l_get_wielded_item(lua_State *L)
262 {
263         ObjectRef *ref = checkobject(L, 1);
264         ServerActiveObject *co = getobject(ref);
265         if(co == NULL){
266                 // Empty ItemStack
267                 LuaItemStack::create(L, ItemStack());
268                 return 1;
269         }
270         // Do it
271         LuaItemStack::create(L, co->getWieldedItem());
272         return 1;
273 }
274
275 // set_wielded_item(self, itemstack or itemstring or table or nil)
276 int ObjectRef::l_set_wielded_item(lua_State *L)
277 {
278         ObjectRef *ref = checkobject(L, 1);
279         ServerActiveObject *co = getobject(ref);
280         if(co == NULL) return 0;
281         // Do it
282         ItemStack item = read_item(L, 2);
283         bool success = co->setWieldedItem(item);
284         lua_pushboolean(L, success);
285         return 1;
286 }
287
288 // set_armor_groups(self, groups)
289 int ObjectRef::l_set_armor_groups(lua_State *L)
290 {
291         ObjectRef *ref = checkobject(L, 1);
292         ServerActiveObject *co = getobject(ref);
293         if(co == NULL) return 0;
294         // Do it
295         ItemGroupList groups;
296         read_groups(L, 2, groups);
297         co->setArmorGroups(groups);
298         return 0;
299 }
300
301 // set_animation(self, frame_range, frame_speed, frame_blend)
302 int ObjectRef::l_set_animation(lua_State *L)
303 {
304         ObjectRef *ref = checkobject(L, 1);
305         ServerActiveObject *co = getobject(ref);
306         if(co == NULL) return 0;
307         // Do it
308         v2f frames = v2f(1, 1);
309         if(!lua_isnil(L, 2))
310                 frames = read_v2f(L, 2);
311         float frame_speed = 15;
312         if(!lua_isnil(L, 3))
313                 frame_speed = lua_tonumber(L, 3);
314         float frame_blend = 0;
315         if(!lua_isnil(L, 4))
316                 frame_blend = lua_tonumber(L, 4);
317         co->setAnimation(frames, frame_speed, frame_blend);
318         return 0;
319 }
320
321 // set_bone_position(self, std::string bone, v3f position, v3f rotation)
322 int ObjectRef::l_set_bone_position(lua_State *L)
323 {
324         ObjectRef *ref = checkobject(L, 1);
325         ServerActiveObject *co = getobject(ref);
326         if(co == NULL) return 0;
327         // Do it
328         std::string bone = "";
329         if(!lua_isnil(L, 2))
330                 bone = lua_tostring(L, 2);
331         v3f position = v3f(0, 0, 0);
332         if(!lua_isnil(L, 3))
333                 position = read_v3f(L, 3);
334         v3f rotation = v3f(0, 0, 0);
335         if(!lua_isnil(L, 4))
336                 rotation = read_v3f(L, 4);
337         co->setBonePosition(bone, position, rotation);
338         return 0;
339 }
340
341 // set_attach(self, parent, bone, position, rotation)
342 int ObjectRef::l_set_attach(lua_State *L)
343 {
344         ObjectRef *ref = checkobject(L, 1);
345         ObjectRef *parent_ref = checkobject(L, 2);
346         ServerActiveObject *co = getobject(ref);
347         ServerActiveObject *parent = getobject(parent_ref);
348         if(co == NULL) return 0;
349         if(parent == NULL) return 0;
350         // Do it
351         std::string bone = "";
352         if(!lua_isnil(L, 3))
353                 bone = lua_tostring(L, 3);
354         v3f position = v3f(0, 0, 0);
355         if(!lua_isnil(L, 4))
356                 position = read_v3f(L, 4);
357         v3f rotation = v3f(0, 0, 0);
358         if(!lua_isnil(L, 5))
359                 rotation = read_v3f(L, 5);
360         co->setAttachment(parent->getId(), bone, position, rotation);
361         return 0;
362 }
363
364 // set_detach(self)
365 int ObjectRef::l_set_detach(lua_State *L)
366 {
367         ObjectRef *ref = checkobject(L, 1);
368         ServerActiveObject *co = getobject(ref);
369         if(co == NULL) return 0;
370         // Do it
371         co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0));
372         return 0;
373 }
374
375 // set_properties(self, properties)
376 int ObjectRef::l_set_properties(lua_State *L)
377 {
378         ObjectRef *ref = checkobject(L, 1);
379         ServerActiveObject *co = getobject(ref);
380         if(co == NULL) return 0;
381         ObjectProperties *prop = co->accessObjectProperties();
382         if(!prop)
383                 return 0;
384         read_object_properties(L, 2, prop);
385         co->notifyObjectPropertiesModified();
386         return 0;
387 }
388
389 /* LuaEntitySAO-only */
390
391 // setvelocity(self, {x=num, y=num, z=num})
392 int ObjectRef::l_setvelocity(lua_State *L)
393 {
394         ObjectRef *ref = checkobject(L, 1);
395         LuaEntitySAO *co = getluaobject(ref);
396         if(co == NULL) return 0;
397         v3f pos = checkFloatPos(L, 2);
398         // Do it
399         co->setVelocity(pos);
400         return 0;
401 }
402
403 // getvelocity(self)
404 int ObjectRef::l_getvelocity(lua_State *L)
405 {
406         ObjectRef *ref = checkobject(L, 1);
407         LuaEntitySAO *co = getluaobject(ref);
408         if(co == NULL) return 0;
409         // Do it
410         v3f v = co->getVelocity();
411         pushFloatPos(L, v);
412         return 1;
413 }
414
415 // setacceleration(self, {x=num, y=num, z=num})
416 int ObjectRef::l_setacceleration(lua_State *L)
417 {
418         ObjectRef *ref = checkobject(L, 1);
419         LuaEntitySAO *co = getluaobject(ref);
420         if(co == NULL) return 0;
421         // pos
422         v3f pos = checkFloatPos(L, 2);
423         // Do it
424         co->setAcceleration(pos);
425         return 0;
426 }
427
428 // getacceleration(self)
429 int ObjectRef::l_getacceleration(lua_State *L)
430 {
431         ObjectRef *ref = checkobject(L, 1);
432         LuaEntitySAO *co = getluaobject(ref);
433         if(co == NULL) return 0;
434         // Do it
435         v3f v = co->getAcceleration();
436         pushFloatPos(L, v);
437         return 1;
438 }
439
440 // setyaw(self, radians)
441 int ObjectRef::l_setyaw(lua_State *L)
442 {
443         ObjectRef *ref = checkobject(L, 1);
444         LuaEntitySAO *co = getluaobject(ref);
445         if(co == NULL) return 0;
446         float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
447         // Do it
448         co->setYaw(yaw);
449         return 0;
450 }
451
452 // getyaw(self)
453 int ObjectRef::l_getyaw(lua_State *L)
454 {
455         ObjectRef *ref = checkobject(L, 1);
456         LuaEntitySAO *co = getluaobject(ref);
457         if(co == NULL) return 0;
458         // Do it
459         float yaw = co->getYaw() * core::DEGTORAD;
460         lua_pushnumber(L, yaw);
461         return 1;
462 }
463
464 // settexturemod(self, mod)
465 int ObjectRef::l_settexturemod(lua_State *L)
466 {
467         ObjectRef *ref = checkobject(L, 1);
468         LuaEntitySAO *co = getluaobject(ref);
469         if(co == NULL) return 0;
470         // Do it
471         std::string mod = luaL_checkstring(L, 2);
472         co->setTextureMod(mod);
473         return 0;
474 }
475
476 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
477 //           select_horiz_by_yawpitch=false)
478 int ObjectRef::l_setsprite(lua_State *L)
479 {
480         ObjectRef *ref = checkobject(L, 1);
481         LuaEntitySAO *co = getluaobject(ref);
482         if(co == NULL) return 0;
483         // Do it
484         v2s16 p(0,0);
485         if(!lua_isnil(L, 2))
486                 p = read_v2s16(L, 2);
487         int num_frames = 1;
488         if(!lua_isnil(L, 3))
489                 num_frames = lua_tonumber(L, 3);
490         float framelength = 0.2;
491         if(!lua_isnil(L, 4))
492                 framelength = lua_tonumber(L, 4);
493         bool select_horiz_by_yawpitch = false;
494         if(!lua_isnil(L, 5))
495                 select_horiz_by_yawpitch = lua_toboolean(L, 5);
496         co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
497         return 0;
498 }
499
500 // DEPRECATED
501 // get_entity_name(self)
502 int ObjectRef::l_get_entity_name(lua_State *L)
503 {
504         ObjectRef *ref = checkobject(L, 1);
505         LuaEntitySAO *co = getluaobject(ref);
506         if(co == NULL) return 0;
507         // Do it
508         std::string name = co->getName();
509         lua_pushstring(L, name.c_str());
510         return 1;
511 }
512
513 // get_luaentity(self)
514 int ObjectRef::l_get_luaentity(lua_State *L)
515 {
516         ObjectRef *ref = checkobject(L, 1);
517         LuaEntitySAO *co = getluaobject(ref);
518         if(co == NULL) return 0;
519         // Do it
520         luaentity_get(L, co->getId());
521         return 1;
522 }
523
524 /* Player-only */
525
526 // is_player(self)
527 int ObjectRef::l_is_player(lua_State *L)
528 {
529         ObjectRef *ref = checkobject(L, 1);
530         Player *player = getplayer(ref);
531         lua_pushboolean(L, (player != NULL));
532         return 1;
533 }
534
535 // get_player_name(self)
536 int ObjectRef::l_get_player_name(lua_State *L)
537 {
538         ObjectRef *ref = checkobject(L, 1);
539         Player *player = getplayer(ref);
540         if(player == NULL){
541                 lua_pushlstring(L, "", 0);
542                 return 1;
543         }
544         // Do it
545         lua_pushstring(L, player->getName());
546         return 1;
547 }
548
549 // get_look_dir(self)
550 int ObjectRef::l_get_look_dir(lua_State *L)
551 {
552         ObjectRef *ref = checkobject(L, 1);
553         Player *player = getplayer(ref);
554         if(player == NULL) return 0;
555         // Do it
556         float pitch = player->getRadPitch();
557         float yaw = player->getRadYaw();
558         v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw));
559         push_v3f(L, v);
560         return 1;
561 }
562
563 // get_look_pitch(self)
564 int ObjectRef::l_get_look_pitch(lua_State *L)
565 {
566         ObjectRef *ref = checkobject(L, 1);
567         Player *player = getplayer(ref);
568         if(player == NULL) return 0;
569         // Do it
570         lua_pushnumber(L, player->getRadPitch());
571         return 1;
572 }
573
574 // get_look_yaw(self)
575 int ObjectRef::l_get_look_yaw(lua_State *L)
576 {
577         ObjectRef *ref = checkobject(L, 1);
578         Player *player = getplayer(ref);
579         if(player == NULL) return 0;
580         // Do it
581         lua_pushnumber(L, player->getRadYaw());
582         return 1;
583 }
584
585 // set_inventory_formspec(self, formspec)
586 int ObjectRef::l_set_inventory_formspec(lua_State *L)
587 {
588         ObjectRef *ref = checkobject(L, 1);
589         Player *player = getplayer(ref);
590         if(player == NULL) return 0;
591         std::string formspec = luaL_checkstring(L, 2);
592
593         player->inventory_formspec = formspec;
594         get_server(L)->reportInventoryFormspecModified(player->getName());
595         lua_pushboolean(L, true);
596         return 1;
597 }
598
599 // get_inventory_formspec(self) -> formspec
600 int ObjectRef::l_get_inventory_formspec(lua_State *L)
601 {
602         ObjectRef *ref = checkobject(L, 1);
603         Player *player = getplayer(ref);
604         if(player == NULL) return 0;
605
606         std::string formspec = player->inventory_formspec;
607         lua_pushlstring(L, formspec.c_str(), formspec.size());
608         return 1;
609 }
610
611 // get_player_control(self)
612 int ObjectRef::l_get_player_control(lua_State *L)
613 {
614         ObjectRef *ref = checkobject(L, 1);
615         Player *player = getplayer(ref);
616         if(player == NULL){
617                 lua_pushlstring(L, "", 0);
618                 return 1;
619         }
620         // Do it
621         PlayerControl control = player->getPlayerControl();
622         lua_newtable(L);
623         lua_pushboolean(L, control.up);
624         lua_setfield(L, -2, "up");
625         lua_pushboolean(L, control.down);
626         lua_setfield(L, -2, "down");
627         lua_pushboolean(L, control.left);
628         lua_setfield(L, -2, "left");
629         lua_pushboolean(L, control.right);
630         lua_setfield(L, -2, "right");
631         lua_pushboolean(L, control.jump);
632         lua_setfield(L, -2, "jump");
633         lua_pushboolean(L, control.aux1);
634         lua_setfield(L, -2, "aux1");
635         lua_pushboolean(L, control.sneak);
636         lua_setfield(L, -2, "sneak");
637         lua_pushboolean(L, control.LMB);
638         lua_setfield(L, -2, "LMB");
639         lua_pushboolean(L, control.RMB);
640         lua_setfield(L, -2, "RMB");
641         return 1;
642 }
643
644 // get_player_control_bits(self)
645 int ObjectRef::l_get_player_control_bits(lua_State *L)
646 {
647         ObjectRef *ref = checkobject(L, 1);
648         Player *player = getplayer(ref);
649         if(player == NULL){
650                 lua_pushlstring(L, "", 0);
651                 return 1;
652         }
653         // Do it
654         lua_pushnumber(L, player->keyPressed);
655         return 1;
656 }
657
658
659 ObjectRef::ObjectRef(ServerActiveObject *object):
660         m_object(object)
661 {
662         //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
663 }
664
665 ObjectRef::~ObjectRef()
666 {
667         /*if(m_object)
668                 infostream<<"ObjectRef destructing for id="
669                                 <<m_object->getId()<<std::endl;
670         else
671                 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
672 }
673
674 // Creates an ObjectRef and leaves it on top of stack
675 // Not callable from Lua; all references are created on the C side.
676 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
677 {
678         ObjectRef *o = new ObjectRef(object);
679         //infostream<<"ObjectRef::create: o="<<o<<std::endl;
680         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
681         luaL_getmetatable(L, className);
682         lua_setmetatable(L, -2);
683 }
684
685 void ObjectRef::set_null(lua_State *L)
686 {
687         ObjectRef *o = checkobject(L, -1);
688         o->m_object = NULL;
689 }
690
691 void ObjectRef::Register(lua_State *L)
692 {
693         lua_newtable(L);
694         int methodtable = lua_gettop(L);
695         luaL_newmetatable(L, className);
696         int metatable = lua_gettop(L);
697
698         lua_pushliteral(L, "__metatable");
699         lua_pushvalue(L, methodtable);
700         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
701
702         lua_pushliteral(L, "__index");
703         lua_pushvalue(L, methodtable);
704         lua_settable(L, metatable);
705
706         lua_pushliteral(L, "__gc");
707         lua_pushcfunction(L, gc_object);
708         lua_settable(L, metatable);
709
710         lua_pop(L, 1);  // drop metatable
711
712         luaL_openlib(L, 0, methods, 0);  // fill methodtable
713         lua_pop(L, 1);  // drop methodtable
714
715         // Cannot be created from Lua
716         //lua_register(L, className, create_object);
717 }
718
719 const char ObjectRef::className[] = "ObjectRef";
720 const luaL_reg ObjectRef::methods[] = {
721         // ServerActiveObject
722         luamethod(ObjectRef, remove),
723         luamethod(ObjectRef, getpos),
724         luamethod(ObjectRef, setpos),
725         luamethod(ObjectRef, moveto),
726         luamethod(ObjectRef, punch),
727         luamethod(ObjectRef, right_click),
728         luamethod(ObjectRef, set_hp),
729         luamethod(ObjectRef, get_hp),
730         luamethod(ObjectRef, get_inventory),
731         luamethod(ObjectRef, get_wield_list),
732         luamethod(ObjectRef, get_wield_index),
733         luamethod(ObjectRef, get_wielded_item),
734         luamethod(ObjectRef, set_wielded_item),
735         luamethod(ObjectRef, set_armor_groups),
736         luamethod(ObjectRef, set_animation),
737         luamethod(ObjectRef, set_bone_position),
738         luamethod(ObjectRef, set_attach),
739         luamethod(ObjectRef, set_detach),
740         luamethod(ObjectRef, set_properties),
741         // LuaEntitySAO-only
742         luamethod(ObjectRef, setvelocity),
743         luamethod(ObjectRef, getvelocity),
744         luamethod(ObjectRef, setacceleration),
745         luamethod(ObjectRef, getacceleration),
746         luamethod(ObjectRef, setyaw),
747         luamethod(ObjectRef, getyaw),
748         luamethod(ObjectRef, settexturemod),
749         luamethod(ObjectRef, setsprite),
750         luamethod(ObjectRef, get_entity_name),
751         luamethod(ObjectRef, get_luaentity),
752         // Player-only
753         luamethod(ObjectRef, is_player),
754         luamethod(ObjectRef, get_player_name),
755         luamethod(ObjectRef, get_look_dir),
756         luamethod(ObjectRef, get_look_pitch),
757         luamethod(ObjectRef, get_look_yaw),
758         luamethod(ObjectRef, set_inventory_formspec),
759         luamethod(ObjectRef, get_inventory_formspec),
760         luamethod(ObjectRef, get_player_control),
761         luamethod(ObjectRef, get_player_control_bits),
762         {0,0}
763 };
764
765 // Creates a new anonymous reference if cobj=NULL or id=0
766 void objectref_get_or_create(lua_State *L,
767                 ServerActiveObject *cobj)
768 {
769         if(cobj == NULL || cobj->getId() == 0){
770                 ObjectRef::create(L, cobj);
771         } else {
772                 objectref_get(L, cobj->getId());
773         }
774 }
775
776 void objectref_get(lua_State *L, u16 id)
777 {
778         // Get minetest.object_refs[i]
779         lua_getglobal(L, "minetest");
780         lua_getfield(L, -1, "object_refs");
781         luaL_checktype(L, -1, LUA_TTABLE);
782         lua_pushnumber(L, id);
783         lua_gettable(L, -2);
784         lua_remove(L, -2); // object_refs
785         lua_remove(L, -2); // minetest
786 }
787
788 /*
789         ObjectProperties
790 */
791
792 void read_object_properties(lua_State *L, int index,
793                 ObjectProperties *prop)
794 {
795         if(index < 0)
796                 index = lua_gettop(L) + 1 + index;
797         if(!lua_istable(L, index))
798                 return;
799
800         prop->hp_max = getintfield_default(L, -1, "hp_max", 10);
801
802         getboolfield(L, -1, "physical", prop->physical);
803
804         getfloatfield(L, -1, "weight", prop->weight);
805
806         lua_getfield(L, -1, "collisionbox");
807         if(lua_istable(L, -1))
808                 prop->collisionbox = read_aabb3f(L, -1, 1.0);
809         lua_pop(L, 1);
810
811         getstringfield(L, -1, "visual", prop->visual);
812
813         getstringfield(L, -1, "mesh", prop->mesh);
814
815         lua_getfield(L, -1, "visual_size");
816         if(lua_istable(L, -1))
817                 prop->visual_size = read_v2f(L, -1);
818         lua_pop(L, 1);
819
820         lua_getfield(L, -1, "textures");
821         if(lua_istable(L, -1)){
822                 prop->textures.clear();
823                 int table = lua_gettop(L);
824                 lua_pushnil(L);
825                 while(lua_next(L, table) != 0){
826                         // key at index -2 and value at index -1
827                         if(lua_isstring(L, -1))
828                                 prop->textures.push_back(lua_tostring(L, -1));
829                         else
830                                 prop->textures.push_back("");
831                         // removes value, keeps key for next iteration
832                         lua_pop(L, 1);
833                 }
834         }
835         lua_pop(L, 1);
836
837         lua_getfield(L, -1, "colors");
838         if(lua_istable(L, -1)){
839                 prop->colors.clear();
840                 int table = lua_gettop(L);
841                 lua_pushnil(L);
842                 while(lua_next(L, table) != 0){
843                         // key at index -2 and value at index -1
844                         if(lua_isstring(L, -1))
845                                 prop->colors.push_back(readARGB8(L, -1));
846                         else
847                                 prop->colors.push_back(video::SColor(255, 255, 255, 255));
848                         // removes value, keeps key for next iteration
849                         lua_pop(L, 1);
850                 }
851         }
852         lua_pop(L, 1);
853
854         lua_getfield(L, -1, "spritediv");
855         if(lua_istable(L, -1))
856                 prop->spritediv = read_v2s16(L, -1);
857         lua_pop(L, 1);
858
859         lua_getfield(L, -1, "initial_sprite_basepos");
860         if(lua_istable(L, -1))
861                 prop->initial_sprite_basepos = read_v2s16(L, -1);
862         lua_pop(L, 1);
863
864         getboolfield(L, -1, "is_visible", prop->is_visible);
865         getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound);
866         getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate);
867 }
868
869 /*
870         object_reference
871 */
872
873 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
874 {
875         realitycheck(L);
876         assert(lua_checkstack(L, 20));
877         //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
878         StackUnroller stack_unroller(L);
879
880         // Create object on stack
881         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
882         int object = lua_gettop(L);
883
884         // Get minetest.object_refs table
885         lua_getglobal(L, "minetest");
886         lua_getfield(L, -1, "object_refs");
887         luaL_checktype(L, -1, LUA_TTABLE);
888         int objectstable = lua_gettop(L);
889
890         // object_refs[id] = object
891         lua_pushnumber(L, cobj->getId()); // Push id
892         lua_pushvalue(L, object); // Copy object to top of stack
893         lua_settable(L, objectstable);
894 }
895
896 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
897 {
898         realitycheck(L);
899         assert(lua_checkstack(L, 20));
900         //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
901         StackUnroller stack_unroller(L);
902
903         // Get minetest.object_refs table
904         lua_getglobal(L, "minetest");
905         lua_getfield(L, -1, "object_refs");
906         luaL_checktype(L, -1, LUA_TTABLE);
907         int objectstable = lua_gettop(L);
908
909         // Get object_refs[id]
910         lua_pushnumber(L, cobj->getId()); // Push id
911         lua_gettable(L, objectstable);
912         // Set object reference to NULL
913         ObjectRef::set_null(L);
914         lua_pop(L, 1); // pop object
915
916         // Set object_refs[id] = nil
917         lua_pushnumber(L, cobj->getId()); // Push id
918         lua_pushnil(L);
919         lua_settable(L, objectstable);
920 }