diff options
-rw-r--r-- | data/mods/default/init.lua | 25 | ||||
-rw-r--r-- | src/scriptapi.cpp | 161 | ||||
-rw-r--r-- | src/server.cpp | 8 |
3 files changed, 177 insertions, 17 deletions
diff --git a/data/mods/default/init.lua b/data/mods/default/init.lua index c59c34fc7..3954c717f 100644 --- a/data/mods/default/init.lua +++ b/data/mods/default/init.lua @@ -44,6 +44,10 @@ -- - remove_node(pos) -- - get_node(pos) -- - add_luaentity(pos, name) +-- - get_meta(pos) -- Get a NodeMetaRef at that position +-- +-- NodeMetaRef +-- - settext(text) -- eg. set the text of a sign -- -- ObjectRef is basically ServerActiveObject. -- ObjectRef methods: @@ -1359,7 +1363,8 @@ minetest.register_on_chat_message(function(name, message) end end) -minetest.register_abm({ +-- Grow papyrus on TNT every 10 seconds +--[[minetest.register_abm({ nodenames = {"TNT"}, interval = 10.0, chance = 1, @@ -1368,7 +1373,23 @@ minetest.register_abm({ pos.y = pos.y + 1 minetest.env:add_node(pos, {name="papyrus"}) end, -}) +})]] + +-- Replace texts of alls signs with "foo" every 10 seconds +--[[minetest.register_abm({ + nodenames = {"sign_wall"}, + interval = 10.0, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + print("ABM: Sign text changed") + local meta = minetest.env:get_meta(pos) + meta:settext("foo") + end, +})]] + +-- LuaNodeMetadata should support something like this +--meta.setvar("somevariable", {x=0, y=0, z=0}) +--meta.getvar("somevariable") -> {x=0, y=0, z=0} -- -- Done, print some random stuff diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 3294ac57f..bf2868907 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -40,14 +40,12 @@ extern "C" { #include "craftdef.h" #include "main.h" // For g_settings #include "settings.h" // For accessing g_settings +#include "nodemetadata.h" +#include "mapblock.h" // For getNodeBlockPos /* TODO: -- Random node triggers (like grass growth) - All kinds of callbacks -- Object visual client-side stuff - - Blink effect - - Spritesheets and animation - LuaNodeMetadata blockdef.metadata_name = "" @@ -62,7 +60,7 @@ TODO: meta.set("owner", playername) meta.get("owner") - Item definition (actually, only CraftItem) -- (not scripting) Putting items in node metadata (virtual) +- Putting items in NodeMetadata (?) */ static void stackDump(lua_State *L, std::ostream &o) @@ -584,6 +582,7 @@ static int l_register_abm(lua_State *L) if(lua_isnil(L, -1)) break; lua_pop(L, 1); + id++; } lua_pop(L, 1); @@ -1038,10 +1037,135 @@ static void luaentity_get(lua_State *L, u16 id) } /* - Reference objects + Reference wrappers */ + #define method(class, name) {#name, class::l_##name} +/* + NodeMetaRef +*/ + +class NodeMetaRef +{ +private: + v3s16 m_p; + ServerEnvironment *m_env; + + static const char className[]; + static const luaL_reg methods[]; + + static NodeMetaRef *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 *(NodeMetaRef**)ud; // unbox pointer + } + + static NodeMetadata* getmeta(NodeMetaRef *ref) + { + NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p); + return meta; + } + + static void reportMetadataChange(NodeMetaRef *ref) + { + // Inform other things that the metadata has changed + v3s16 blockpos = getNodeBlockPos(ref->m_p); + MapEditEvent event; + event.type = MEET_BLOCK_NODE_METADATA_CHANGED; + event.p = blockpos; + ref->m_env->getMap().dispatchEvent(&event); + // Set the block to be saved + MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos); + if(block) + block->raiseModified(MOD_STATE_WRITE_NEEDED, "l_settext"); + } + + // Exported functions + + // garbage collector + static int gc_object(lua_State *L) { + NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1)); + delete o; + return 0; + } + + // settext(self, text) + static int l_settext(lua_State *L) + { + NodeMetaRef *ref = checkobject(L, 1); + NodeMetadata *meta = getmeta(ref); + if(meta == NULL) return 0; + // Do it + std::string text = lua_tostring(L, 2); + meta->setText(text); + // Inform other things that the metadata has changed + reportMetadataChange(ref); + return 0; + } + +public: + NodeMetaRef(v3s16 p, ServerEnvironment *env): + m_p(p), + m_env(env) + { + } + + ~NodeMetaRef() + { + } + + // Creates an NodeMetaRef and leaves it on top of stack + // Not callable from Lua; all references are created on the C side. + static void create(lua_State *L, v3s16 p, ServerEnvironment *env) + { + NodeMetaRef *o = new NodeMetaRef(p, env); + //infostream<<"NodeMetaRef::create: o="<<o<<std::endl; + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + } + + static void Register(lua_State *L) + { + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // drop methodtable + + // Cannot be created from Lua + //lua_register(L, className, create_object); + } +}; +const char NodeMetaRef::className[] = "NodeMetaRef"; +const luaL_reg NodeMetaRef::methods[] = { + method(NodeMetaRef, settext), + {0,0} +}; + +/* + EnvRef +*/ + class EnvRef { private: @@ -1129,6 +1253,19 @@ private: return 0; } + // EnvRef:get_meta(pos) + static int l_get_meta(lua_State *L) + { + infostream<<"EnvRef::l_get_meta()"<<std::endl; + EnvRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if(env == NULL) return 0; + // Do it + v3s16 p = readpos(L, 2); + NodeMetaRef::create(L, p, env); + return 1; + } + static int gc_object(lua_State *L) { EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1)); delete o; @@ -1198,9 +1335,14 @@ const luaL_reg EnvRef::methods[] = { method(EnvRef, remove_node), method(EnvRef, get_node), method(EnvRef, add_luaentity), + method(EnvRef, get_meta), {0,0} }; +/* + ObjectRef +*/ + class ObjectRef { private: @@ -1536,11 +1678,10 @@ void scriptapi_export(lua_State *L, Server *server) // Put functions in metatable luaL_register(L, NULL, minetest_entity_m); // Put other stuff in metatable - - // Environment C reference + + // Register reference wrappers + NodeMetaRef::Register(L); EnvRef::Register(L); - - // Object C reference ObjectRef::Register(L); } diff --git a/src/server.cpp b/src/server.cpp index bb91749af..51f8814fe 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3190,12 +3190,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) NodeMetadata *meta = m_env->getMap().getNodeMetadata(p); if(!meta) return; - if(meta->typeId() != LEGN(m_nodedef, "CONTENT_SIGN_WALL")) - return; - SignNodeMetadata *signmeta = (SignNodeMetadata*)meta; - signmeta->setText(text); + + meta->setText(text); - actionstream<<player->getName()<<" writes \""<<text<<"\" to sign " + actionstream<<player->getName()<<" writes \""<<text<<"\" to sign" <<" at "<<PP(p)<<std::endl; v3s16 blockpos = getNodeBlockPos(p); |