3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
20 #include "scriptapi.h"
21 #include "scriptapi_object.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"
35 ObjectRef* ObjectRef::checkobject(lua_State *L, int narg)
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
43 ServerActiveObject* ObjectRef::getobject(ObjectRef *ref)
45 ServerActiveObject *co = ref->m_object;
49 LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
51 ServerActiveObject *obj = getobject(ref);
54 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
56 return (LuaEntitySAO*)obj;
59 PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
61 ServerActiveObject *obj = getobject(ref);
64 if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
66 return (PlayerSAO*)obj;
69 Player* ObjectRef::getplayer(ObjectRef *ref)
71 PlayerSAO *playersao = getplayersao(ref);
74 return playersao->getPlayer();
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;
88 int ObjectRef::l_remove(lua_State *L)
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;
99 // returns: {x=num, y=num, z=num}
100 int ObjectRef::l_getpos(lua_State *L)
102 ObjectRef *ref = checkobject(L, 1);
103 ServerActiveObject *co = getobject(ref);
104 if(co == NULL) return 0;
105 v3f pos = co->getBasePosition() / BS;
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");
117 int ObjectRef::l_setpos(lua_State *L)
119 ObjectRef *ref = checkobject(L, 1);
120 //LuaEntitySAO *co = getluaobject(ref);
121 ServerActiveObject *co = getobject(ref);
122 if(co == NULL) return 0;
124 v3f pos = checkFloatPos(L, 2);
130 // moveto(self, pos, continuous=false)
131 int ObjectRef::l_moveto(lua_State *L)
133 ObjectRef *ref = checkobject(L, 1);
134 //LuaEntitySAO *co = getluaobject(ref);
135 ServerActiveObject *co = getobject(ref);
136 if(co == NULL) return 0;
138 v3f pos = checkFloatPos(L, 2);
140 bool continuous = lua_toboolean(L, 3);
142 co->moveTo(pos, continuous);
146 // punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
147 int ObjectRef::l_punch(lua_State *L)
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;
156 if(lua_type(L, 5) != LUA_TTABLE)
157 dir = co->getBasePosition() - puncher->getBasePosition();
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);
166 co->punch(dir, &toolcap, puncher, time_from_last_punch);
170 // right_click(self, clicker); clicker = an another ObjectRef
171 int ObjectRef::l_right_click(lua_State *L)
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;
185 // hp = number of hitpoints (2 * number of hearts)
187 int ObjectRef::l_set_hp(lua_State *L)
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;*/
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)
207 ObjectRef *ref = checkobject(L, 1);
208 ServerActiveObject *co = getobject(ref);
211 lua_pushnumber(L, 1);
214 int hp = co->getHP();
215 /*infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
216 <<" hp="<<hp<<std::endl;*/
218 lua_pushnumber(L, hp);
222 // get_inventory(self)
223 int ObjectRef::l_get_inventory(lua_State *L)
225 ObjectRef *ref = checkobject(L, 1);
226 ServerActiveObject *co = getobject(ref);
227 if(co == NULL) return 0;
229 InventoryLocation loc = co->getInventoryLocation();
230 if(get_server(L)->getInventory(loc) != NULL)
231 InvRef::create(L, loc);
233 lua_pushnil(L); // An object may have no inventory (nil)
237 // get_wield_list(self)
238 int ObjectRef::l_get_wield_list(lua_State *L)
240 ObjectRef *ref = checkobject(L, 1);
241 ServerActiveObject *co = getobject(ref);
242 if(co == NULL) return 0;
244 lua_pushstring(L, co->getWieldList().c_str());
248 // get_wield_index(self)
249 int ObjectRef::l_get_wield_index(lua_State *L)
251 ObjectRef *ref = checkobject(L, 1);
252 ServerActiveObject *co = getobject(ref);
253 if(co == NULL) return 0;
255 lua_pushinteger(L, co->getWieldIndex() + 1);
259 // get_wielded_item(self)
260 int ObjectRef::l_get_wielded_item(lua_State *L)
262 ObjectRef *ref = checkobject(L, 1);
263 ServerActiveObject *co = getobject(ref);
266 LuaItemStack::create(L, ItemStack());
270 LuaItemStack::create(L, co->getWieldedItem());
274 // set_wielded_item(self, itemstack or itemstring or table or nil)
275 int ObjectRef::l_set_wielded_item(lua_State *L)
277 ObjectRef *ref = checkobject(L, 1);
278 ServerActiveObject *co = getobject(ref);
279 if(co == NULL) return 0;
281 ItemStack item = read_item(L, 2);
282 bool success = co->setWieldedItem(item);
283 lua_pushboolean(L, success);
287 // set_armor_groups(self, groups)
288 int ObjectRef::l_set_armor_groups(lua_State *L)
290 ObjectRef *ref = checkobject(L, 1);
291 ServerActiveObject *co = getobject(ref);
292 if(co == NULL) return 0;
294 ItemGroupList groups;
295 read_groups(L, 2, groups);
296 co->setArmorGroups(groups);
300 // set_animation(self, frame_range, frame_speed, frame_blend)
301 int ObjectRef::l_set_animation(lua_State *L)
303 ObjectRef *ref = checkobject(L, 1);
304 ServerActiveObject *co = getobject(ref);
305 if(co == NULL) return 0;
307 v2f frames = v2f(1, 1);
309 frames = read_v2f(L, 2);
310 float frame_speed = 15;
312 frame_speed = lua_tonumber(L, 3);
313 float frame_blend = 0;
315 frame_blend = lua_tonumber(L, 4);
316 co->setAnimation(frames, frame_speed, frame_blend);
320 // set_bone_position(self, std::string bone, v3f position, v3f rotation)
321 int ObjectRef::l_set_bone_position(lua_State *L)
323 ObjectRef *ref = checkobject(L, 1);
324 ServerActiveObject *co = getobject(ref);
325 if(co == NULL) return 0;
327 std::string bone = "";
329 bone = lua_tostring(L, 2);
330 v3f position = v3f(0, 0, 0);
332 position = read_v3f(L, 3);
333 v3f rotation = v3f(0, 0, 0);
335 rotation = read_v3f(L, 4);
336 co->setBonePosition(bone, position, rotation);
340 // set_attach(self, parent, bone, position, rotation)
341 int ObjectRef::l_set_attach(lua_State *L)
343 ObjectRef *ref = checkobject(L, 1);
344 ObjectRef *parent_ref = checkobject(L, 2);
345 ServerActiveObject *co = getobject(ref);
346 ServerActiveObject *parent = getobject(parent_ref);
347 if(co == NULL) return 0;
348 if(parent == NULL) return 0;
350 std::string bone = "";
352 bone = lua_tostring(L, 3);
353 v3f position = v3f(0, 0, 0);
355 position = read_v3f(L, 4);
356 v3f rotation = v3f(0, 0, 0);
358 rotation = read_v3f(L, 5);
359 co->setAttachment(parent->getId(), bone, position, rotation);
364 int ObjectRef::l_set_detach(lua_State *L)
366 ObjectRef *ref = checkobject(L, 1);
367 ServerActiveObject *co = getobject(ref);
368 if(co == NULL) return 0;
370 co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0));
374 // set_properties(self, properties)
375 int ObjectRef::l_set_properties(lua_State *L)
377 ObjectRef *ref = checkobject(L, 1);
378 ServerActiveObject *co = getobject(ref);
379 if(co == NULL) return 0;
380 ObjectProperties *prop = co->accessObjectProperties();
383 read_object_properties(L, 2, prop);
384 co->notifyObjectPropertiesModified();
388 /* LuaEntitySAO-only */
390 // setvelocity(self, {x=num, y=num, z=num})
391 int ObjectRef::l_setvelocity(lua_State *L)
393 ObjectRef *ref = checkobject(L, 1);
394 LuaEntitySAO *co = getluaobject(ref);
395 if(co == NULL) return 0;
396 v3f pos = checkFloatPos(L, 2);
398 co->setVelocity(pos);
403 int ObjectRef::l_getvelocity(lua_State *L)
405 ObjectRef *ref = checkobject(L, 1);
406 LuaEntitySAO *co = getluaobject(ref);
407 if(co == NULL) return 0;
409 v3f v = co->getVelocity();
414 // setacceleration(self, {x=num, y=num, z=num})
415 int ObjectRef::l_setacceleration(lua_State *L)
417 ObjectRef *ref = checkobject(L, 1);
418 LuaEntitySAO *co = getluaobject(ref);
419 if(co == NULL) return 0;
421 v3f pos = checkFloatPos(L, 2);
423 co->setAcceleration(pos);
427 // getacceleration(self)
428 int ObjectRef::l_getacceleration(lua_State *L)
430 ObjectRef *ref = checkobject(L, 1);
431 LuaEntitySAO *co = getluaobject(ref);
432 if(co == NULL) return 0;
434 v3f v = co->getAcceleration();
439 // setyaw(self, radians)
440 int ObjectRef::l_setyaw(lua_State *L)
442 ObjectRef *ref = checkobject(L, 1);
443 LuaEntitySAO *co = getluaobject(ref);
444 if(co == NULL) return 0;
445 float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
452 int ObjectRef::l_getyaw(lua_State *L)
454 ObjectRef *ref = checkobject(L, 1);
455 LuaEntitySAO *co = getluaobject(ref);
456 if(co == NULL) return 0;
458 float yaw = co->getYaw() * core::DEGTORAD;
459 lua_pushnumber(L, yaw);
463 // settexturemod(self, mod)
464 int ObjectRef::l_settexturemod(lua_State *L)
466 ObjectRef *ref = checkobject(L, 1);
467 LuaEntitySAO *co = getluaobject(ref);
468 if(co == NULL) return 0;
470 std::string mod = luaL_checkstring(L, 2);
471 co->setTextureMod(mod);
475 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
476 // select_horiz_by_yawpitch=false)
477 int ObjectRef::l_setsprite(lua_State *L)
479 ObjectRef *ref = checkobject(L, 1);
480 LuaEntitySAO *co = getluaobject(ref);
481 if(co == NULL) return 0;
485 p = read_v2s16(L, 2);
488 num_frames = lua_tonumber(L, 3);
489 float framelength = 0.2;
491 framelength = lua_tonumber(L, 4);
492 bool select_horiz_by_yawpitch = false;
494 select_horiz_by_yawpitch = lua_toboolean(L, 5);
495 co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
500 // get_entity_name(self)
501 int ObjectRef::l_get_entity_name(lua_State *L)
503 ObjectRef *ref = checkobject(L, 1);
504 LuaEntitySAO *co = getluaobject(ref);
505 if(co == NULL) return 0;
507 std::string name = co->getName();
508 lua_pushstring(L, name.c_str());
512 // get_luaentity(self)
513 int ObjectRef::l_get_luaentity(lua_State *L)
515 ObjectRef *ref = checkobject(L, 1);
516 LuaEntitySAO *co = getluaobject(ref);
517 if(co == NULL) return 0;
519 luaentity_get(L, co->getId());
526 int ObjectRef::l_is_player(lua_State *L)
528 ObjectRef *ref = checkobject(L, 1);
529 Player *player = getplayer(ref);
530 lua_pushboolean(L, (player != NULL));
534 // get_player_name(self)
535 int ObjectRef::l_get_player_name(lua_State *L)
537 ObjectRef *ref = checkobject(L, 1);
538 Player *player = getplayer(ref);
540 lua_pushlstring(L, "", 0);
544 lua_pushstring(L, player->getName());
548 // get_look_dir(self)
549 int ObjectRef::l_get_look_dir(lua_State *L)
551 ObjectRef *ref = checkobject(L, 1);
552 Player *player = getplayer(ref);
553 if(player == NULL) return 0;
555 float pitch = player->getRadPitch();
556 float yaw = player->getRadYaw();
557 v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw));
562 // get_look_pitch(self)
563 int ObjectRef::l_get_look_pitch(lua_State *L)
565 ObjectRef *ref = checkobject(L, 1);
566 Player *player = getplayer(ref);
567 if(player == NULL) return 0;
569 lua_pushnumber(L, player->getRadPitch());
573 // get_look_yaw(self)
574 int ObjectRef::l_get_look_yaw(lua_State *L)
576 ObjectRef *ref = checkobject(L, 1);
577 Player *player = getplayer(ref);
578 if(player == NULL) return 0;
580 lua_pushnumber(L, player->getRadYaw());
584 // set_look_pitch(self, radians)
585 int ObjectRef::l_set_look_pitch(lua_State *L)
587 ObjectRef *ref = checkobject(L, 1);
588 PlayerSAO* co = getplayersao(ref);
589 if(co == NULL) return 0;
590 float pitch = luaL_checknumber(L, 2) * core::RADTODEG;
596 // set_look_yaw(self, radians)
597 int ObjectRef::l_set_look_yaw(lua_State *L)
599 ObjectRef *ref = checkobject(L, 1);
600 PlayerSAO* co = getplayersao(ref);
601 if(co == NULL) return 0;
602 float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
608 // set_inventory_formspec(self, formspec)
609 int ObjectRef::l_set_inventory_formspec(lua_State *L)
611 ObjectRef *ref = checkobject(L, 1);
612 Player *player = getplayer(ref);
613 if(player == NULL) return 0;
614 std::string formspec = luaL_checkstring(L, 2);
616 player->inventory_formspec = formspec;
617 get_server(L)->reportInventoryFormspecModified(player->getName());
618 lua_pushboolean(L, true);
622 // get_inventory_formspec(self) -> formspec
623 int ObjectRef::l_get_inventory_formspec(lua_State *L)
625 ObjectRef *ref = checkobject(L, 1);
626 Player *player = getplayer(ref);
627 if(player == NULL) return 0;
629 std::string formspec = player->inventory_formspec;
630 lua_pushlstring(L, formspec.c_str(), formspec.size());
634 // get_player_control(self)
635 int ObjectRef::l_get_player_control(lua_State *L)
637 ObjectRef *ref = checkobject(L, 1);
638 Player *player = getplayer(ref);
640 lua_pushlstring(L, "", 0);
644 PlayerControl control = player->getPlayerControl();
646 lua_pushboolean(L, control.up);
647 lua_setfield(L, -2, "up");
648 lua_pushboolean(L, control.down);
649 lua_setfield(L, -2, "down");
650 lua_pushboolean(L, control.left);
651 lua_setfield(L, -2, "left");
652 lua_pushboolean(L, control.right);
653 lua_setfield(L, -2, "right");
654 lua_pushboolean(L, control.jump);
655 lua_setfield(L, -2, "jump");
656 lua_pushboolean(L, control.aux1);
657 lua_setfield(L, -2, "aux1");
658 lua_pushboolean(L, control.sneak);
659 lua_setfield(L, -2, "sneak");
660 lua_pushboolean(L, control.LMB);
661 lua_setfield(L, -2, "LMB");
662 lua_pushboolean(L, control.RMB);
663 lua_setfield(L, -2, "RMB");
667 // get_player_control_bits(self)
668 int ObjectRef::l_get_player_control_bits(lua_State *L)
670 ObjectRef *ref = checkobject(L, 1);
671 Player *player = getplayer(ref);
673 lua_pushlstring(L, "", 0);
677 lua_pushnumber(L, player->keyPressed);
682 ObjectRef::ObjectRef(ServerActiveObject *object):
685 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
688 ObjectRef::~ObjectRef()
691 infostream<<"ObjectRef destructing for id="
692 <<m_object->getId()<<std::endl;
694 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
697 // Creates an ObjectRef and leaves it on top of stack
698 // Not callable from Lua; all references are created on the C side.
699 void ObjectRef::create(lua_State *L, ServerActiveObject *object)
701 ObjectRef *o = new ObjectRef(object);
702 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
703 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
704 luaL_getmetatable(L, className);
705 lua_setmetatable(L, -2);
708 void ObjectRef::set_null(lua_State *L)
710 ObjectRef *o = checkobject(L, -1);
714 void ObjectRef::Register(lua_State *L)
717 int methodtable = lua_gettop(L);
718 luaL_newmetatable(L, className);
719 int metatable = lua_gettop(L);
721 lua_pushliteral(L, "__metatable");
722 lua_pushvalue(L, methodtable);
723 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
725 lua_pushliteral(L, "__index");
726 lua_pushvalue(L, methodtable);
727 lua_settable(L, metatable);
729 lua_pushliteral(L, "__gc");
730 lua_pushcfunction(L, gc_object);
731 lua_settable(L, metatable);
733 lua_pop(L, 1); // drop metatable
735 luaL_openlib(L, 0, methods, 0); // fill methodtable
736 lua_pop(L, 1); // drop methodtable
738 // Cannot be created from Lua
739 //lua_register(L, className, create_object);
742 const char ObjectRef::className[] = "ObjectRef";
743 const luaL_reg ObjectRef::methods[] = {
744 // ServerActiveObject
745 luamethod(ObjectRef, remove),
746 luamethod(ObjectRef, getpos),
747 luamethod(ObjectRef, setpos),
748 luamethod(ObjectRef, moveto),
749 luamethod(ObjectRef, punch),
750 luamethod(ObjectRef, right_click),
751 luamethod(ObjectRef, set_hp),
752 luamethod(ObjectRef, get_hp),
753 luamethod(ObjectRef, get_inventory),
754 luamethod(ObjectRef, get_wield_list),
755 luamethod(ObjectRef, get_wield_index),
756 luamethod(ObjectRef, get_wielded_item),
757 luamethod(ObjectRef, set_wielded_item),
758 luamethod(ObjectRef, set_armor_groups),
759 luamethod(ObjectRef, set_animation),
760 luamethod(ObjectRef, set_bone_position),
761 luamethod(ObjectRef, set_attach),
762 luamethod(ObjectRef, set_detach),
763 luamethod(ObjectRef, set_properties),
765 luamethod(ObjectRef, setvelocity),
766 luamethod(ObjectRef, getvelocity),
767 luamethod(ObjectRef, setacceleration),
768 luamethod(ObjectRef, getacceleration),
769 luamethod(ObjectRef, setyaw),
770 luamethod(ObjectRef, getyaw),
771 luamethod(ObjectRef, settexturemod),
772 luamethod(ObjectRef, setsprite),
773 luamethod(ObjectRef, get_entity_name),
774 luamethod(ObjectRef, get_luaentity),
776 luamethod(ObjectRef, is_player),
777 luamethod(ObjectRef, get_player_name),
778 luamethod(ObjectRef, get_look_dir),
779 luamethod(ObjectRef, get_look_pitch),
780 luamethod(ObjectRef, get_look_yaw),
781 luamethod(ObjectRef, set_look_yaw),
782 luamethod(ObjectRef, set_look_pitch),
783 luamethod(ObjectRef, set_inventory_formspec),
784 luamethod(ObjectRef, get_inventory_formspec),
785 luamethod(ObjectRef, get_player_control),
786 luamethod(ObjectRef, get_player_control_bits),
790 // Creates a new anonymous reference if cobj=NULL or id=0
791 void objectref_get_or_create(lua_State *L,
792 ServerActiveObject *cobj)
794 if(cobj == NULL || cobj->getId() == 0){
795 ObjectRef::create(L, cobj);
797 objectref_get(L, cobj->getId());
801 void objectref_get(lua_State *L, u16 id)
803 // Get minetest.object_refs[i]
804 lua_getglobal(L, "minetest");
805 lua_getfield(L, -1, "object_refs");
806 luaL_checktype(L, -1, LUA_TTABLE);
807 lua_pushnumber(L, id);
809 lua_remove(L, -2); // object_refs
810 lua_remove(L, -2); // minetest
817 void read_object_properties(lua_State *L, int index,
818 ObjectProperties *prop)
821 index = lua_gettop(L) + 1 + index;
822 if(!lua_istable(L, index))
825 prop->hp_max = getintfield_default(L, -1, "hp_max", 10);
827 getboolfield(L, -1, "physical", prop->physical);
829 getfloatfield(L, -1, "weight", prop->weight);
831 lua_getfield(L, -1, "collisionbox");
832 if(lua_istable(L, -1))
833 prop->collisionbox = read_aabb3f(L, -1, 1.0);
836 getstringfield(L, -1, "visual", prop->visual);
838 getstringfield(L, -1, "mesh", prop->mesh);
840 lua_getfield(L, -1, "visual_size");
841 if(lua_istable(L, -1))
842 prop->visual_size = read_v2f(L, -1);
845 lua_getfield(L, -1, "textures");
846 if(lua_istable(L, -1)){
847 prop->textures.clear();
848 int table = lua_gettop(L);
850 while(lua_next(L, table) != 0){
851 // key at index -2 and value at index -1
852 if(lua_isstring(L, -1))
853 prop->textures.push_back(lua_tostring(L, -1));
855 prop->textures.push_back("");
856 // removes value, keeps key for next iteration
862 lua_getfield(L, -1, "colors");
863 if(lua_istable(L, -1)){
864 prop->colors.clear();
865 int table = lua_gettop(L);
867 while(lua_next(L, table) != 0){
868 // key at index -2 and value at index -1
869 if(lua_isstring(L, -1))
870 prop->colors.push_back(readARGB8(L, -1));
872 prop->colors.push_back(video::SColor(255, 255, 255, 255));
873 // removes value, keeps key for next iteration
879 lua_getfield(L, -1, "spritediv");
880 if(lua_istable(L, -1))
881 prop->spritediv = read_v2s16(L, -1);
884 lua_getfield(L, -1, "initial_sprite_basepos");
885 if(lua_istable(L, -1))
886 prop->initial_sprite_basepos = read_v2s16(L, -1);
889 getboolfield(L, -1, "is_visible", prop->is_visible);
890 getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound);
891 getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate);
898 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
901 assert(lua_checkstack(L, 20));
902 //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
903 StackUnroller stack_unroller(L);
905 // Create object on stack
906 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
907 int object = lua_gettop(L);
909 // Get minetest.object_refs table
910 lua_getglobal(L, "minetest");
911 lua_getfield(L, -1, "object_refs");
912 luaL_checktype(L, -1, LUA_TTABLE);
913 int objectstable = lua_gettop(L);
915 // object_refs[id] = object
916 lua_pushnumber(L, cobj->getId()); // Push id
917 lua_pushvalue(L, object); // Copy object to top of stack
918 lua_settable(L, objectstable);
921 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
924 assert(lua_checkstack(L, 20));
925 //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
926 StackUnroller stack_unroller(L);
928 // Get minetest.object_refs table
929 lua_getglobal(L, "minetest");
930 lua_getfield(L, -1, "object_refs");
931 luaL_checktype(L, -1, LUA_TTABLE);
932 int objectstable = lua_gettop(L);
934 // Get object_refs[id]
935 lua_pushnumber(L, cobj->getId()); // Push id
936 lua_gettable(L, objectstable);
937 // Set object reference to NULL
938 ObjectRef::set_null(L);
939 lua_pop(L, 1); // pop object
941 // Set object_refs[id] = nil
942 lua_pushnumber(L, cobj->getId()); // Push id
944 lua_settable(L, objectstable);