/* Minetest-c55 Copyright (C) 2011 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "scriptapi.h" #include extern "C" { #include #include #include } #include "log.h" #include "server.h" #include "porting.h" #include "filesys.h" #include "serverobject.h" #include "script.h" //#include "luna.h" #include "luaentity_common.h" /* TODO: - Global environment step function - Random node triggers - Object network and client-side stuff - Named node types and dynamic id allocation - LuaNodeMetadata blockdef.has_metadata = true/false - Stores an inventory and stuff in a Settings object meta.inventory_add_list("main") blockdef.on_inventory_modified meta.set("owner", playername) meta.get("owner") */ static void stackDump(lua_State *L, std::ostream &o) { int i; int top = lua_gettop(L); for (i = 1; i <= top; i++) { /* repeat for each level */ int t = lua_type(L, i); switch (t) { case LUA_TSTRING: /* strings */ o<<"\""<= 30){ dstream<<"Stack is over 30:"< stack top // registered_entities[name] = object lua_setfield(L, registered_entities, name); // Get registered object to top of stack lua_pushvalue(L, 2); // Set __index to point to itself lua_pushvalue(L, -1); lua_setfield(L, -2, "__index"); // Set metatable.__index = metatable luaL_getmetatable(L, "minetest.entity"); lua_pushvalue(L, -1); // duplicate metatable lua_setfield(L, -2, "__index"); // Set object metatable lua_setmetatable(L, -2); return 0; /* number of results */ } static const struct luaL_Reg minetest_f [] = { {"register_entity", l_register_entity}, {NULL, NULL} }; static int l_entity_set_deleted(lua_State *L) { return 0; } static const struct luaL_Reg minetest_entity_m [] = { {"set_deleted", l_entity_set_deleted}, {NULL, NULL} }; static void objectref_get(lua_State *L, u16 id) { // Get minetest.object_refs[i] lua_getglobal(L, "minetest"); lua_getfield(L, -1, "object_refs"); luaL_checktype(L, -1, LUA_TTABLE); lua_pushnumber(L, id); lua_gettable(L, -2); lua_remove(L, -2); // object_refs lua_remove(L, -2); // minetest } static void luaentity_get(lua_State *L, u16 id) { // Get minetest.luaentities[i] lua_getglobal(L, "minetest"); lua_getfield(L, -1, "luaentities"); luaL_checktype(L, -1, LUA_TTABLE); lua_pushnumber(L, id); lua_gettable(L, -2); lua_remove(L, -2); // luaentities lua_remove(L, -2); // minetest } /* Reference objects */ #define method(class, name) {#name, class::l_##name} class EnvRef { private: ServerEnvironment *m_env; static const char className[]; static const luaL_reg methods[]; static EnvRef *checkobject(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TUSERDATA); void *ud = luaL_checkudata(L, narg, className); if(!ud) luaL_typerror(L, narg, className); return *(EnvRef**)ud; // unbox pointer } // Exported functions // EnvRef:add_node(pos, content) // pos = {x=num, y=num, z=num} // content = number static int l_add_node(lua_State *L) { infostream<<"EnvRef::l_add_node()"<m_env; if(env == NULL) return 0; // pos v3s16 pos; lua_pushvalue(L, 2); // Push pos luaL_checktype(L, -1, LUA_TTABLE); lua_getfield(L, -1, "x"); pos.X = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "y"); pos.Y = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "z"); pos.Z = lua_tonumber(L, -1); lua_pop(L, 1); lua_pop(L, 1); // Pop pos // content u16 content = 0; lua_pushvalue(L, 3); // Push content content = lua_tonumber(L, -1); lua_pop(L, 1); // Pop content // Do it env->getMap().addNodeWithEvent(pos, MapNode(content)); return 0; } static int gc_object(lua_State *L) { EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1)); delete o; return 0; } public: EnvRef(ServerEnvironment *env): m_env(env) { infostream<<"EnvRef created"<m_object; if(co == NULL) return 0; infostream<<"ObjectRef::l_remove(): id="<getId()<m_removed = true; return 0; } static int l_getpos(lua_State *L) { ObjectRef *o = checkobject(L, 1); ServerActiveObject *co = o->m_object; if(co == NULL) return 0; infostream<<"ObjectRef::l_getpos(): id="<getId()<getBasePosition() / BS; lua_newtable(L); lua_pushnumber(L, pos.X); lua_setfield(L, -2, "x"); lua_pushnumber(L, pos.Y); lua_setfield(L, -2, "y"); lua_pushnumber(L, pos.Z); lua_setfield(L, -2, "z"); return 1; } static int gc_object(lua_State *L) { //ObjectRef *o = checkobject(L, 1); ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1)); //infostream<<"ObjectRef::gc_object: o="<getId()); // Push id lua_pushvalue(L, object); // Copy object to top of stack lua_settable(L, objectstable); // pop object_refs, minetest and the object lua_pop(L, 3); } void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj) { realitycheck(L); assert(lua_checkstack(L, 20)); infostream<<"scriptapi_rm_object_reference: id="<getId()<getId()); // Push id lua_gettable(L, objectstable); // Set object reference to NULL ObjectRef::set_null(L); lua_pop(L, 1); // pop object // Set object_refs[id] = nil lua_pushnumber(L, cobj->getId()); // Push id lua_pushnil(L); lua_settable(L, objectstable); // pop object_refs, minetest lua_pop(L, 2); } /* luaentity */ void scriptapi_luaentity_add(lua_State *L, u16 id, const char *name, const char *init_state) { realitycheck(L); assert(lua_checkstack(L, 20)); infostream<<"scriptapi_luaentity_add: id="<physical = lua_toboolean(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "weight"); prop->weight = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "collisionbox"); if(lua_istable(L, -1)){ lua_rawgeti(L, -1, 1); prop->collisionbox.MinEdge.X = lua_tonumber(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 2); prop->collisionbox.MinEdge.Y = lua_tonumber(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 3); prop->collisionbox.MinEdge.Z = lua_tonumber(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 4); prop->collisionbox.MaxEdge.X = lua_tonumber(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 5); prop->collisionbox.MaxEdge.Y = lua_tonumber(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 6); prop->collisionbox.MaxEdge.Z = lua_tonumber(L, -1); lua_pop(L, 1); } lua_pop(L, 1); lua_getfield(L, -1, "visual"); if(lua_isstring(L, -1)) prop->visual = lua_tostring(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "textures"); if(lua_istable(L, -1)){ prop->textures.clear(); int table = lua_gettop(L); lua_pushnil(L); while(lua_next(L, table) != 0){ // key at index -2 and value at index -1 if(lua_isstring(L, -1)) prop->textures.push_back(lua_tostring(L, -1)); else prop->textures.push_back(""); // removes value, keeps key for next iteration lua_pop(L, 1); } } lua_pop(L, 1); } void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime) { realitycheck(L); assert(lua_checkstack(L, 20)); //infostream<<"scriptapi_luaentity_step: id="<