Scripting WIP; Lua entity step callback works
parent
1ddfdc55dd
commit
41c91391fc
|
@ -61,7 +61,7 @@ end]]
|
||||||
return s
|
return s
|
||||||
end]]
|
end]]
|
||||||
|
|
||||||
function basic_serialize(o)
|
function basic_dump2(o)
|
||||||
if type(o) == "number" then
|
if type(o) == "number" then
|
||||||
return tostring(o)
|
return tostring(o)
|
||||||
elseif type(o) == "string" then
|
elseif type(o) == "string" then
|
||||||
|
@ -70,6 +70,8 @@ function basic_serialize(o)
|
||||||
return tostring(o)
|
return tostring(o)
|
||||||
elseif type(o) == "function" then
|
elseif type(o) == "function" then
|
||||||
return "<function>"
|
return "<function>"
|
||||||
|
elseif type(o) == "userdata" then
|
||||||
|
return "<userdata>"
|
||||||
elseif type(o) == "nil" then
|
elseif type(o) == "nil" then
|
||||||
return "nil"
|
return "nil"
|
||||||
else
|
else
|
||||||
|
@ -78,13 +80,14 @@ function basic_serialize(o)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function serialize(o, name, dumped)
|
function dump2(o, name, dumped)
|
||||||
name = name or "_"
|
name = name or "_"
|
||||||
dumped = dumped or {}
|
dumped = dumped or {}
|
||||||
io.write(name, " = ")
|
io.write(name, " = ")
|
||||||
if type(o) == "number" or type(o) == "string" or type(o) == "boolean"
|
if type(o) == "number" or type(o) == "string" or type(o) == "boolean"
|
||||||
or type(o) == "function" or type(o) == "nil" then
|
or type(o) == "function" or type(o) == "nil"
|
||||||
io.write(basic_serialize(o), "\n")
|
or type(o) == "userdata" then
|
||||||
|
io.write(basic_dump2(o), "\n")
|
||||||
elseif type(o) == "table" then
|
elseif type(o) == "table" then
|
||||||
if dumped[o] then
|
if dumped[o] then
|
||||||
io.write(dumped[o], "\n")
|
io.write(dumped[o], "\n")
|
||||||
|
@ -92,8 +95,8 @@ function serialize(o, name, dumped)
|
||||||
dumped[o] = name
|
dumped[o] = name
|
||||||
io.write("{}\n") -- new table
|
io.write("{}\n") -- new table
|
||||||
for k,v in pairs(o) do
|
for k,v in pairs(o) do
|
||||||
local fieldname = string.format("%s[%s]", name, basic_serialize(k))
|
local fieldname = string.format("%s[%s]", name, basic_dump2(k))
|
||||||
serialize(v, fieldname, dumped)
|
dump2(v, fieldname, dumped)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -131,8 +134,6 @@ end
|
||||||
print("omg lol")
|
print("omg lol")
|
||||||
print("minetest dump: "..dump(minetest))
|
print("minetest dump: "..dump(minetest))
|
||||||
|
|
||||||
minetest.register_entity("a", "dummy string");
|
|
||||||
|
|
||||||
--local TNT = minetest.new_entity {
|
--local TNT = minetest.new_entity {
|
||||||
local TNT = {
|
local TNT = {
|
||||||
-- Maybe handle gravity and collision this way? dunno
|
-- Maybe handle gravity and collision this way? dunno
|
||||||
|
@ -148,30 +149,34 @@ local TNT = {
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Called after object is created
|
-- Called after object is created
|
||||||
function TNT:on_create(env)
|
function TNT:on_create()
|
||||||
|
print("TNT:on_create()")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Called periodically
|
-- Called periodically
|
||||||
function TNT:on_step(env, dtime)
|
function TNT:on_step(dtime)
|
||||||
self.timer = self.timer + dtime
|
print("TNT:on_step()")
|
||||||
|
--[[self.timer = self.timer + dtime
|
||||||
if self.timer > 4.0 then
|
if self.timer > 4.0 then
|
||||||
self.to_be_deleted = true -- Environment will delete this object at a suitable point of execution
|
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
|
env:explode(self.pos, 3) -- Uh... well, something like that
|
||||||
end
|
end]]
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Called when object is punched
|
-- Called when object is punched
|
||||||
function TNT:on_punch(env, hitter)
|
function TNT:on_punch(hitter)
|
||||||
-- If tool is bomb defuser, revert back to being a block
|
print("TNT:on_punch()")
|
||||||
|
--[[-- If tool is bomb defuser, revert back to being a block
|
||||||
local item = hitter.inventory.get_current()
|
local item = hitter.inventory.get_current()
|
||||||
if item.itemtype == "tool" and item.param == "bomb_defuser" then
|
if item.itemtype == "tool" and item.param == "bomb_defuser" then
|
||||||
env:add_node(self.pos, 3072)
|
env:add_node(self.pos, 3072)
|
||||||
self.to_be_deleted = true
|
self.to_be_deleted = true
|
||||||
end
|
end]]
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Called when object is right-clicked
|
-- Called when object is right-clicked
|
||||||
function TNT:on_rightclick(self, env, hitter)
|
function TNT:on_rightclick(clicker)
|
||||||
|
print("TNT:on_rightclick()")
|
||||||
end
|
end
|
||||||
|
|
||||||
print("TNT dump: "..dump(TNT))
|
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: "..dump(minetest.registered_entities))
|
||||||
print("minetest.registered_entities:")
|
print("minetest.registered_entities:")
|
||||||
serialize(minetest.registered_entities)
|
dump2(minetest.registered_entities)
|
||||||
|
|
||||||
|
|
|
@ -1516,7 +1516,7 @@ LuaEntitySAO::~LuaEntitySAO()
|
||||||
{
|
{
|
||||||
if(m_registered){
|
if(m_registered){
|
||||||
lua_State *L = m_env->getLua();
|
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
|
// Create entity by name and state
|
||||||
m_registered = true;
|
m_registered = true;
|
||||||
lua_State *L = m_env->getLua();
|
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,
|
ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos,
|
||||||
|
@ -1553,7 +1553,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
||||||
{
|
{
|
||||||
if(m_registered){
|
if(m_registered){
|
||||||
lua_State *L = m_env->getLua();
|
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
|
// state
|
||||||
if(m_registered){
|
if(m_registered){
|
||||||
lua_State *L = m_env->getLua();
|
lua_State *L = m_env->getLua();
|
||||||
scriptapi_luaentity_deregister(L, m_id);
|
|
||||||
std::string state = scriptapi_luaentity_get_state(L, m_id);
|
std::string state = scriptapi_luaentity_get_state(L, m_id);
|
||||||
os<<serializeLongString(state);
|
os<<serializeLongString(state);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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)
|
static int l_register_entity(lua_State *L)
|
||||||
{
|
{
|
||||||
const char *name = luaL_checkstring(L, 1);
|
const char *name = luaL_checkstring(L, 1);
|
||||||
luaL_checkany(L, 2);
|
luaL_checktype(L, 2, LUA_TTABLE);
|
||||||
infostream<<"register_entity: "<<name<<std::endl;
|
infostream<<"register_entity: "<<name<<std::endl;
|
||||||
// Get the minetest table
|
|
||||||
|
// Get minetest.registered_entities
|
||||||
lua_getglobal(L, "minetest");
|
lua_getglobal(L, "minetest");
|
||||||
// Get field "registered_entities"
|
|
||||||
lua_getfield(L, -1, "registered_entities");
|
lua_getfield(L, -1, "registered_entities");
|
||||||
luaL_checktype(L, -1, LUA_TTABLE);
|
luaL_checktype(L, -1, LUA_TTABLE);
|
||||||
int objectstable = lua_gettop(L);
|
int registered_entities = lua_gettop(L);
|
||||||
// Object is in param 2
|
lua_pushvalue(L, 2); // Object = param 2 -> stack top
|
||||||
lua_pushvalue(L, 2); // Copy object to top of stack
|
// registered_entities[name] = object
|
||||||
lua_setfield(L, objectstable, name); // 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 */
|
return 0; /* number of results */
|
||||||
}
|
}
|
||||||
|
@ -286,36 +301,76 @@ void scriptapi_export(lua_State *L, Server *server)
|
||||||
ObjectRef::Register(L);
|
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)
|
const char *init_state)
|
||||||
{
|
{
|
||||||
realitycheck(L);
|
realitycheck(L);
|
||||||
assert(lua_checkstack(L, 20));
|
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)
|
// 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);
|
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
|
// Get minetest.luaentities table
|
||||||
lua_getglobal(L, "minetest");
|
lua_getglobal(L, "minetest");
|
||||||
lua_getfield(L, -1, "luaentities");
|
lua_getfield(L, -1, "luaentities");
|
||||||
luaL_checktype(L, -1, LUA_TTABLE);
|
luaL_checktype(L, -1, LUA_TTABLE);
|
||||||
int objectstable = lua_gettop(L);
|
int luaentities = lua_gettop(L);
|
||||||
|
|
||||||
// luaentities[id] = object
|
// luaentities[id] = object
|
||||||
lua_pushnumber(L, id); // Push id
|
lua_pushnumber(L, id); // Push id
|
||||||
lua_pushvalue(L, object); // Copy object to top of stack
|
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);
|
realitycheck(L);
|
||||||
assert(lua_checkstack(L, 20));
|
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
|
// Get minetest.luaentities table
|
||||||
lua_getglobal(L, "minetest");
|
lua_getglobal(L, "minetest");
|
||||||
|
@ -337,24 +392,35 @@ void scriptapi_luaentity_deregister(lua_State *L, u16 id)
|
||||||
lua_pop(L, 2); // pop luaentities, minetest
|
lua_pop(L, 2); // pop luaentities, minetest
|
||||||
}
|
}
|
||||||
|
|
||||||
void scriptapi_luaentity_step(lua_State *L, u16 id,
|
void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
|
||||||
float dtime, bool send_recommended)
|
|
||||||
{
|
{
|
||||||
realitycheck(L);
|
realitycheck(L);
|
||||||
assert(lua_checkstack(L, 20));
|
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_getglobal(L, "minetest");
|
||||||
lua_getfield(L, -1, "luaentities");
|
lua_getfield(L, -1, "luaentities");
|
||||||
luaL_checktype(L, -1, LUA_TTABLE);
|
luaL_checktype(L, -1, LUA_TTABLE);
|
||||||
int objectstable = lua_gettop(L);
|
lua_pushnumber(L, id);
|
||||||
|
lua_gettable(L, -2);
|
||||||
// Get luaentities[id]
|
int object = lua_gettop(L);
|
||||||
lua_pushnumber(L, id); // Push id
|
// State: object is at top of stack
|
||||||
lua_gettable(L, objectstable);
|
/*dump2(L, "entity");
|
||||||
|
lua_getmetatable(L, -1);
|
||||||
// TODO: Call step function
|
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, 1); // pop object
|
||||||
lua_pop(L, 2); // pop luaentities, minetest
|
lua_pop(L, 2); // pop luaentities, minetest
|
||||||
|
|
|
@ -32,11 +32,10 @@ void scriptapi_export(lua_State *L, Server *server);
|
||||||
void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj);
|
void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj);
|
||||||
void scriptapi_rm_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);
|
const char *init_state);
|
||||||
void scriptapi_luaentity_deregister(lua_State *L, u16 id);
|
void scriptapi_luaentity_rm(lua_State *L, u16 id);
|
||||||
void scriptapi_luaentity_step(lua_State *L, u16 id,
|
void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime);
|
||||||
float dtime, bool send_recommended);
|
|
||||||
std::string scriptapi_luaentity_get_state(lua_State *L, u16 id);
|
std::string scriptapi_luaentity_get_state(lua_State *L, u16 id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue