/*MinetestCopyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>This program is free software; you can redistribute it and/or modifyit under the terms of the GNU Lesser General Public License as published bythe Free Software Foundation; either version 2.1 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU Lesser General Public License for more details.You should have received a copy of the GNU Lesser General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.*/#include"cpp_api/s_entity.h"#include"cpp_api/s_internal.h"#include"log.h"#include"object_properties.h"#include"common/c_converter.h"#include"common/c_content.h"boolScriptApiEntity::luaentity_Add(u16 id,const char*name){
SCRIPTAPI_PRECHECKHEADER
verbosestream<<"scriptapi_luaentity_add: id="<<id<<" name=\""<<name<<"\""<<std::endl;// Get core.registered_entities[name]lua_getglobal(L,"core");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);if(lua_type(L, -1) != LUA_TTABLE){
errorstream<<"LuaEntity name\""<<name<<"\"not defined"<<std::endl;return false;}int prototype_table =lua_gettop(L);//dump2(L, "prototype_table");// Create entity objectlua_newtable(L);int object =lua_gettop(L);// Set object metatablelua_pushvalue(L, prototype_table);lua_setmetatable(L, -2);// Add object reference// This should be userdata with metatable ObjectRefobjectrefGet(L, id);luaL_checktype(L, -1, LUA_TUSERDATA);if(!luaL_checkudata(L, -1,"ObjectRef"))luaL_typerror(L, -1,"ObjectRef");lua_setfield(L, -2,"object");// core.luaentities[id] = objectlua_getglobal(L,"core");lua_getfield(L, -1,"luaentities");luaL_checktype(L, -1, LUA_TTABLE);lua_pushnumber(L, id);// Push idlua_pushvalue(L, object);// Copy object to top of stacklua_settable(L, -3);return true;}voidScriptApiEntity::luaentity_Activate(u16 id,conststd::string &staticdata, u32 dtime_s){
SCRIPTAPI_PRECHECKHEADER
verbosestream <<"scriptapi_luaentity_activate: id="<< id <<std::endl;int error_handler =PUSH_ERROR_HANDLER(L);// Get core.luaentities[id]luaentity_get(L, id);int object =lua_gettop(L);// Get on_activate functionlua_getfield(L, -1,"on_activate");if(!lua_isnil(L, -1)) {luaL_checktype(L, -1, LUA_TFUNCTION);lua_pushvalue(L, object);// selflua_pushlstring(L, staticdata.c_str(), staticdata.size());lua_pushinteger(L, dtime_s);setOriginFromTable(object);PCALL_RES(lua_pcall(L,3,0, error_handler));}else{lua_pop(L,1);}lua_pop(L,2);// Pop object and error handler}voidScriptApiEntity::luaentity_Remove(u16 id){
SCRIPTAPI_PRECHECKHEADER
verbosestream <<"scriptapi_luaentity_rm: id="<< id <<std::endl;// Get core.luaentities tablelua_getglobal(L,"core");lua_getfield(L, -1,"luaentities");luaL_checktype(L, -1, LUA_TTABLE);int objectstable =lua_gettop(L);// Set luaentities[id] = nillua_pushnumber(L, id);// Push idlua_pushnil(L);lua_settable(L, objectstable);lua_pop(L,2);// pop luaentities, core}std::string ScriptApiEntity::luaentity_GetStaticdata(u16 id){
SCRIPTAPI_PRECHECKHEADER
//infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;int error_handler =PUSH_ERROR_HANDLER(L);// Get core.luaentities[id]luaentity_get(L, id);int object =lua_gettop(L);// Get get_staticdata functionlua_getfield(L, -1,"get_staticdata");if(lua_isnil(L, -1)) {lua_pop(L,2);// Pop entity and get_staticdatareturn"";}luaL_checktype(L, -1, LUA_TFUNCTION);lua_pushvalue(L, object);// selfsetOriginFromTable(object);PCALL_RES(lua_pcall(L,1,1, error_handler));lua_remove(L, object);lua_remove(L, error_handler);size_t len =0;const char*s =lua_tolstring(L, -1, &len);lua_pop(L,1);// Pop static datareturnstd::string(s, len);}voidScriptApiEntity::luaentity_GetProperties(u16 id,
ObjectProperties *prop){
SCRIPTAPI_PRECHECKHEADER
//infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;// Get core.luaentities[id]luaentity_get(L, id);// Set default values that differ from ObjectProperties defaults
prop->hp_max =10;/* Read stuff */
prop->hp_max =getintfield_default(L, -1,"hp_max",10);getboolfield(L, -1,"physical", prop->physical);getboolfield(L, -1,"collide_with_objects", prop->collideWithObjects);getfloatfield(L, -1,"weight", prop->weight);lua_getfield(L, -1,"collisionbox");if(lua_istable(L, -1))
prop->collisionbox =read_aabb3f(L, -1,1.0);lua_pop(L,1);getstringfield(L, -1,"visual", prop->visual);getstringfield(L, -1,"mesh", prop->mesh);// Deprecated: read object properties directlyread_object_properties(L, -1, prop);// Read initial_propertieslua_getfield(L, -1,"initial_properties");read_object_properties(L, -1, prop);lua_pop(L,1);}voidScriptApiEntity::luaentity_Step(u16 id,float dtime){
SCRIPTAPI_PRECHECKHEADER
//infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;int error_handler =PUSH_ERROR_HANDLER(L);// Get core.luaentities[id]luaentity_get(L, id);int object =lua_gettop(L);// State: object is at top of stack// Get step functionlua_getfield(L, -1,"on_step");if(lua_isnil(L, -1)) {lua_pop(L,2);// Pop on_step and entityreturn;}luaL_checktype(L, -1, LUA_TFUNCTION);lua_pushvalue(L, object);// selflua_pushnumber(L, dtime);// dtimesetOriginFromTable(object);PCALL_RES(lua_pcall(L,2,0, error_handler));lua_pop(L,2);// Pop object and error handler}// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch,// tool_capabilities, direction)voidScriptApiEntity::luaentity_Punch(u16 id,
ServerActiveObject *puncher,float time_from_last_punch,const ToolCapabilities *toolcap, v3f dir){
SCRIPTAPI_PRECHECKHEADER
//infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;int error_handler =PUSH_ERROR_HANDLER(L);// Get core.luaentities[id]luaentity_get(L,id);int object =lua_gettop(L);// State: object is at top of stack// Get functionlua_getfield(L, -1,"on_punch");if(lua_isnil(L, -1)) {lua_pop(L,2);// Pop on_punch and entitureturn;}luaL_checktype(L, -1, LUA_TFUNCTION);lua_pushvalue(L, object);// selfobjectrefGetOrCreate(L, puncher);// Clicker referencelua_pushnumber(L, time_from_last_punch);push_tool_capabilities(L, *toolcap);push_v3f(L, dir);setOriginFromTable(object);PCALL_RES(lua_pcall(L,5,0, error_handler));lua_pop(L,2);// Pop object and error handler}// Calls entity:on_rightclick(ObjectRef clicker)voidScriptApiEntity::luaentity_Rightclick(u16 id,
ServerActiveObject *clicker){
SCRIPTAPI_PRECHECKHEADER
//infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;int error_handler =PUSH_ERROR_HANDLER(L);// Get core.luaentities[id]luaentity_get(L, id);int object =lua_gettop(L);// State: object is at top of stack// Get functionlua_getfield(L, -1,"on_rightclick");if(lua_isnil(L, -1)) {lua_pop(L,2);// Pop on_rightclick and entityreturn;}luaL_checktype(L, -1, LUA_TFUNCTION);lua_pushvalue(L, object);// selfobjectrefGetOrCreate(L, clicker);// Clicker referencesetOriginFromTable(object);PCALL_RES(lua_pcall(L,2,0, error_handler));lua_pop(L,2);// Pop object and error handler}