diff options
author | Perttu Ahola <celeron55@gmail.com> | 2011-11-12 00:46:05 +0200 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2011-11-29 19:13:39 +0200 |
commit | 41c91391fce65147aa7f3b5ceb7db5758709199a (patch) | |
tree | de7e00d20b4639ed5751f542b7c43f90fd0e313f | |
parent | 1ddfdc55dd01e8b9739f0754a496efabfd4a3ff1 (diff) | |
download | minetest-41c91391fce65147aa7f3b5ceb7db5758709199a.tar.gz minetest-41c91391fce65147aa7f3b5ceb7db5758709199a.tar.bz2 minetest-41c91391fce65147aa7f3b5ceb7db5758709199a.zip |
Scripting WIP; Lua entity step callback works
-rw-r--r-- | data/scripts/default.lua | 39 | ||||
-rw-r--r-- | src/content_sao.cpp | 7 | ||||
-rw-r--r-- | src/scriptapi.cpp | 120 | ||||
-rw-r--r-- | src/scriptapi.h | 7 |
4 files changed, 121 insertions, 52 deletions
diff --git a/data/scripts/default.lua b/data/scripts/default.lua index c525ecf1e..005e9ac15 100644 --- a/data/scripts/default.lua +++ b/data/scripts/default.lua @@ -61,7 +61,7 @@ end]] return s end]] -function basic_serialize(o) +function basic_dump2(o) if type(o) == "number" then return tostring(o) elseif type(o) == "string" then @@ -70,6 +70,8 @@ function basic_serialize(o) return tostring(o) elseif type(o) == "function" then return "<function>" + elseif type(o) == "userdata" then + return "<userdata>" elseif type(o) == "nil" then return "nil" else @@ -78,13 +80,14 @@ function basic_serialize(o) end end -function serialize(o, name, dumped) +function dump2(o, name, dumped) name = name or "_" dumped = dumped or {} io.write(name, " = ") if type(o) == "number" or type(o) == "string" or type(o) == "boolean" - or type(o) == "function" or type(o) == "nil" then - io.write(basic_serialize(o), "\n") + or type(o) == "function" or type(o) == "nil" + or type(o) == "userdata" then + io.write(basic_dump2(o), "\n") elseif type(o) == "table" then if dumped[o] then io.write(dumped[o], "\n") @@ -92,8 +95,8 @@ function serialize(o, name, dumped) dumped[o] = name io.write("{}\n") -- new table for k,v in pairs(o) do - local fieldname = string.format("%s[%s]", name, basic_serialize(k)) - serialize(v, fieldname, dumped) + local fieldname = string.format("%s[%s]", name, basic_dump2(k)) + dump2(v, fieldname, dumped) end end else @@ -131,8 +134,6 @@ end print("omg lol") print("minetest dump: "..dump(minetest)) -minetest.register_entity("a", "dummy string"); - --local TNT = minetest.new_entity { local TNT = { -- Maybe handle gravity and collision this way? dunno @@ -148,30 +149,34 @@ local TNT = { } -- Called after object is created -function TNT:on_create(env) +function TNT:on_create() + print("TNT:on_create()") end -- Called periodically -function TNT:on_step(env, dtime) - self.timer = self.timer + dtime +function TNT:on_step(dtime) + print("TNT:on_step()") + --[[self.timer = self.timer + dtime if self.timer > 4.0 then self.to_be_deleted = true -- Environment will delete this object at a suitable point of execution env:explode(self.pos, 3) -- Uh... well, something like that - end + end]] end -- Called when object is punched -function TNT:on_punch(env, hitter) - -- If tool is bomb defuser, revert back to being a block +function TNT:on_punch(hitter) + print("TNT:on_punch()") + --[[-- If tool is bomb defuser, revert back to being a block local item = hitter.inventory.get_current() if item.itemtype == "tool" and item.param == "bomb_defuser" then env:add_node(self.pos, 3072) self.to_be_deleted = true - end + end]] end -- Called when object is right-clicked -function TNT:on_rightclick(self, env, hitter) +function TNT:on_rightclick(clicker) + print("TNT:on_rightclick()") end print("TNT dump: "..dump(TNT)) @@ -181,5 +186,5 @@ minetest.register_entity("TNT", TNT) --print("minetest.registered_entities: "..dump(minetest.registered_entities)) print("minetest.registered_entities:") -serialize(minetest.registered_entities) +dump2(minetest.registered_entities) diff --git a/src/content_sao.cpp b/src/content_sao.cpp index d1303b471..3507ec154 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -1516,7 +1516,7 @@ LuaEntitySAO::~LuaEntitySAO() { if(m_registered){ lua_State *L = m_env->getLua(); - scriptapi_luaentity_deregister(L, m_id); + scriptapi_luaentity_rm(L, m_id); } } @@ -1527,7 +1527,7 @@ void LuaEntitySAO::addedToEnvironment(u16 id) // Create entity by name and state m_registered = true; lua_State *L = m_env->getLua(); - scriptapi_luaentity_register(L, id, m_init_name.c_str(), m_init_state.c_str()); + scriptapi_luaentity_add(L, id, m_init_name.c_str(), m_init_state.c_str()); } ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos, @@ -1553,7 +1553,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) { if(m_registered){ lua_State *L = m_env->getLua(); - scriptapi_luaentity_step(L, m_id, dtime, send_recommended); + scriptapi_luaentity_step(L, m_id, dtime); } } @@ -1578,7 +1578,6 @@ std::string LuaEntitySAO::getStaticData() // state if(m_registered){ lua_State *L = m_env->getLua(); - scriptapi_luaentity_deregister(L, m_id); std::string state = scriptapi_luaentity_get_state(L, m_id); os<<serializeLongString(state); } else { diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index d055c1976..fc5364c87 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -76,21 +76,36 @@ static void realitycheck(lua_State *L) } } -// Register new object prototype (must be based on entity) +// Register new object prototype +// register_entity(name, prototype) static int l_register_entity(lua_State *L) { const char *name = luaL_checkstring(L, 1); - luaL_checkany(L, 2); + luaL_checktype(L, 2, LUA_TTABLE); infostream<<"register_entity: "<<name<<std::endl; - // Get the minetest table + + // Get minetest.registered_entities lua_getglobal(L, "minetest"); - // Get field "registered_entities" lua_getfield(L, -1, "registered_entities"); luaL_checktype(L, -1, LUA_TTABLE); - int objectstable = lua_gettop(L); - // Object is in param 2 - lua_pushvalue(L, 2); // Copy object to top of stack - lua_setfield(L, objectstable, name); // registered_entities[name] = object + int registered_entities = lua_gettop(L); + lua_pushvalue(L, 2); // Object = param 2 -> 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 */ } @@ -286,36 +301,76 @@ void scriptapi_export(lua_State *L, Server *server) ObjectRef::Register(L); } -void scriptapi_luaentity_register(lua_State *L, u16 id, const char *name, +// Dump stack top with the dump2 function +static void dump2(lua_State *L, const char *name) +{ + // Dump object (debug) + lua_getglobal(L, "dump2"); + luaL_checktype(L, -1, LUA_TFUNCTION); + lua_pushvalue(L, -2); // Get previous stack top as first parameter + lua_pushstring(L, name); + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s\n", lua_tostring(L, -1)); +} + +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_register: id="<<id<<std::endl; + infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\"" + <<name<<"\""<<std::endl; + + int initial_top = lua_gettop(L); // Create object as a dummy string (TODO: Create properly) - lua_pushstring(L, "dummy object string"); + + // Get minetest.registered_entities[name] + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_entities"); + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushstring(L, name); + lua_gettable(L, -2); + // Should be a table, which we will use as a prototype + luaL_checktype(L, -1, LUA_TTABLE); + int prototype_table = lua_gettop(L); + //dump2(L, "prototype_table"); + + // Create entity object + lua_newtable(L); int object = lua_gettop(L); + // Set object metatable + lua_pushvalue(L, prototype_table); + lua_setmetatable(L, -2); + + /*// Set prototype_table.__index = prototype_table + lua_pushvalue(L, prototype_table); // Copy to top of stack + lua_pushvalue(L, -1); // duplicate prototype_table + lua_setfield(L, -2, "__index");*/ + + /*lua_pushstring(L, "debug from C"); + lua_setfield(L, -2, "on_step");*/ + // Get minetest.luaentities table lua_getglobal(L, "minetest"); lua_getfield(L, -1, "luaentities"); luaL_checktype(L, -1, LUA_TTABLE); - int objectstable = lua_gettop(L); + int luaentities = lua_gettop(L); // luaentities[id] = object lua_pushnumber(L, id); // Push id lua_pushvalue(L, object); // Copy object to top of stack - lua_settable(L, objectstable); + lua_settable(L, luaentities); - lua_pop(L, 3); // pop luaentities, minetest and the object + lua_settop(L, initial_top); // Reset stack } -void scriptapi_luaentity_deregister(lua_State *L, u16 id) +void scriptapi_luaentity_rm(lua_State *L, u16 id) { realitycheck(L); assert(lua_checkstack(L, 20)); - infostream<<"scriptapi_luaentity_deregister: id="<<id<<std::endl; + infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl; // Get minetest.luaentities table lua_getglobal(L, "minetest"); @@ -337,24 +392,35 @@ void scriptapi_luaentity_deregister(lua_State *L, u16 id) lua_pop(L, 2); // pop luaentities, minetest } -void scriptapi_luaentity_step(lua_State *L, u16 id, - float dtime, bool send_recommended) +void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime) { realitycheck(L); assert(lua_checkstack(L, 20)); - //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl; + infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl; - // Get minetest.luaentities table + // Get minetest.luaentities[i] lua_getglobal(L, "minetest"); lua_getfield(L, -1, "luaentities"); luaL_checktype(L, -1, LUA_TTABLE); - int objectstable = lua_gettop(L); - - // Get luaentities[id] - lua_pushnumber(L, id); // Push id - lua_gettable(L, objectstable); - - // TODO: Call step function + lua_pushnumber(L, id); + lua_gettable(L, -2); + int object = lua_gettop(L); + // State: object is at top of stack + /*dump2(L, "entity"); + lua_getmetatable(L, -1); + dump2(L, "getmetatable(entity)"); + lua_getfield(L, -1, "__index"); + dump2(L, "getmetatable(entity).__index"); + lua_pop(L, 1); + lua_pop(L, 1);*/ + // Get step function + lua_getfield(L, -1, "on_step"); + luaL_checktype(L, -1, LUA_TFUNCTION); + lua_pushvalue(L, object); // self + lua_pushnumber(L, dtime); // dtime + // Call with 2 arguments, 0 results + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error running function 'step': %s\n", lua_tostring(L, -1)); lua_pop(L, 1); // pop object lua_pop(L, 2); // pop luaentities, minetest diff --git a/src/scriptapi.h b/src/scriptapi.h index a97d707a8..18c2b3838 100644 --- a/src/scriptapi.h +++ b/src/scriptapi.h @@ -32,11 +32,10 @@ void scriptapi_export(lua_State *L, Server *server); void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj); void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj); -void scriptapi_luaentity_register(lua_State *L, u16 id, const char *name, +void scriptapi_luaentity_add(lua_State *L, u16 id, const char *name, const char *init_state); -void scriptapi_luaentity_deregister(lua_State *L, u16 id); -void scriptapi_luaentity_step(lua_State *L, u16 id, - float dtime, bool send_recommended); +void scriptapi_luaentity_rm(lua_State *L, u16 id); +void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime); std::string scriptapi_luaentity_get_state(lua_State *L, u16 id); #endif |