From d6b30dd3a5df4b84a287305f807442064f4cf68d Mon Sep 17 00:00:00 2001 From: Kahrl Date: Tue, 29 Nov 2011 17:15:18 +0200 Subject: CraftItem rework and Lua interface --- src/scriptapi.cpp | 335 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) (limited to 'src/scriptapi.cpp') diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 3918bdfc3..83efef670 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -39,11 +39,13 @@ extern "C" { #include "tooldef.h" #include "nodedef.h" #include "craftdef.h" +#include "craftitemdef.h" #include "main.h" // For g_settings #include "settings.h" // For accessing g_settings #include "nodemetadata.h" #include "mapblock.h" // For getNodeBlockPos #include "content_nodemeta.h" +#include "utility.h" static void stackDump(lua_State *L, std::ostream &o) { @@ -615,6 +617,55 @@ static int l_register_tool(lua_State *L) return 0; /* number of results */ } +// register_craftitem(name, {lots of stuff}) +static int l_register_craftitem(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + infostream<<"register_craftitem: "<getWritableCraftItemDefManager(); + + // Check if on_drop is defined + lua_getfield(L, table, "on_drop"); + bool got_on_drop = !lua_isnil(L, -1); + lua_pop(L, 1); + + // Check if on_use is defined + lua_getfield(L, table, "on_use"); + bool got_on_use = !lua_isnil(L, -1); + lua_pop(L, 1); + + CraftItemDefinition def; + + getstringfield(L, table, "image", def.imagename); + getstringfield(L, table, "cookresult_item", def.cookresult_item); + getfloatfield(L, table, "furnace_cooktime", def.furnace_cooktime); + getfloatfield(L, table, "furnace_burntime", def.furnace_burntime); + def.usable = getboolfield_default(L, table, "usable", got_on_use); + getboolfield(L, table, "liquids_pointable", def.liquids_pointable); + def.dropcount = getintfield_default(L, table, "dropcount", def.dropcount); + def.stack_max = getintfield_default(L, table, "stack_max", def.stack_max); + + // If an on_drop callback is defined, force dropcount to 1 + if (got_on_drop) + def.dropcount = 1; + + // Register it + craftitemdef->registerCraftItem(name, def); + + lua_pushvalue(L, table); + scriptapi_add_craftitem(L, name); + + return 0; /* number of results */ +} + // register_node(name, {lots of stuff}) static int l_register_node(lua_State *L) { @@ -976,6 +1027,7 @@ static const struct luaL_Reg minetest_f [] = { {"register_nodedef_defaults", l_register_nodedef_defaults}, {"register_entity", l_register_entity}, {"register_tool", l_register_tool}, + {"register_craftitem", l_register_craftitem}, {"register_node", l_register_node}, {"register_craft", l_register_craft}, {"register_abm", l_register_abm}, @@ -1541,6 +1593,56 @@ private: return 0; } + // EnvRef:add_item(pos, inventorystring) + // pos = {x=num, y=num, z=num} + static int l_add_item(lua_State *L) + { + infostream<<"EnvRef::l_add_item()"<m_env; + if(env == NULL) return 0; + // pos + v3f pos = readFloatPos(L, 2); + // inventorystring + const char *inventorystring = lua_tostring(L, 3); + // Do it + ServerActiveObject *obj = new ItemSAO(env, pos, inventorystring); + env->addActiveObject(obj); + return 0; + } + + // EnvRef:add_rat(pos) + // pos = {x=num, y=num, z=num} + static int l_add_rat(lua_State *L) + { + infostream<<"EnvRef::l_add_rat()"<m_env; + if(env == NULL) return 0; + // pos + v3f pos = readFloatPos(L, 2); + // Do it + ServerActiveObject *obj = new RatSAO(env, pos); + env->addActiveObject(obj); + return 0; + } + + // EnvRef:add_firefly(pos) + // pos = {x=num, y=num, z=num} + static int l_add_firefly(lua_State *L) + { + infostream<<"EnvRef::l_add_firefly()"<m_env; + if(env == NULL) return 0; + // pos + v3f pos = readFloatPos(L, 2); + // Do it + ServerActiveObject *obj = new FireflySAO(env, pos); + env->addActiveObject(obj); + return 0; + } + // EnvRef:get_meta(pos) static int l_get_meta(lua_State *L) { @@ -1623,6 +1725,9 @@ const luaL_reg EnvRef::methods[] = { method(EnvRef, remove_node), method(EnvRef, get_node), method(EnvRef, add_luaentity), + method(EnvRef, add_item), + method(EnvRef, add_rat), + method(EnvRef, add_firefly), method(EnvRef, get_meta), {0,0} }; @@ -1663,6 +1768,16 @@ private: return (LuaEntitySAO*)obj; } + static ServerRemotePlayer* getplayer(ObjectRef *ref) + { + ServerActiveObject *obj = getobject(ref); + if(obj == NULL) + return NULL; + if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER) + return NULL; + return static_cast(obj); + } + // Exported functions // garbage collector @@ -1795,6 +1910,64 @@ private: return 1; } + // add_to_inventory_later(self, itemstring) + // returns: nil + static int l_add_to_inventory_later(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + luaL_checkstring(L, 2); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // itemstring + const char *itemstring = lua_tostring(L, 2); + infostream<<"ObjectRef::l_add_to_inventory_later(): id="<getId() + <<" itemstring=\""<getEnv(); + assert(env); + IGameDef *gamedef = env->getGameDef(); + InventoryItem *item = InventoryItem::deSerialize(is, gamedef); + infostream<<"item="<addToInventoryLater(item); + // Return + return 0; + } + + // get_hp(self) + // returns: number of hitpoints (2 * number of hearts) + // 0 if not applicable to this type of object + static int l_get_hp(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + int hp = co->getHP(); + infostream<<"ObjectRef::l_get_hp(): id="<getId() + <<" hp="< 0); + + // Set minetest.registered_craftitems[name] = table on top of stack + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_craftitems"); + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushvalue(L, -3); // push another reference to the table to be registered + lua_setfield(L, -2, name); // set minetest.registered_craftitems[name] +} + +static bool get_craftitem_callback(lua_State *L, const char *name, + const char *callbackname) +{ + // Get minetest.registered_craftitems[name][callbackname] + // If that is nil or on error, return false and stack is unchanged + // If that is a function, returns true and pushes the + // function onto the stack + + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_craftitems"); + lua_remove(L, -2); + luaL_checktype(L, -1, LUA_TTABLE); + lua_getfield(L, -1, name); + lua_remove(L, -2); + // Should be a table + if(lua_type(L, -1) != LUA_TTABLE) + { + errorstream<<"CraftItem name \""<