]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/script/lua_api/l_item.cpp
Merge branch 'master' of https://github.com/minetest/minetest
[dragonfireclient.git] / src / script / lua_api / l_item.cpp
index 0c174feca3fe5e25b49ecc4fca68059b70b743d4..bae6701a095eb803a50ad704a7853a5c06ed2b97 100644 (file)
@@ -22,13 +22,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "lua_api/l_internal.h"
 #include "common/c_converter.h"
 #include "common/c_content.h"
+#include "common/c_packer.h"
 #include "itemdef.h"
 #include "nodedef.h"
 #include "server.h"
-#include "content_sao.h"
 #include "inventory.h"
 #include "log.h"
-
+#include "script/cpp_api/s_base.h"
+#ifndef SERVER
+#include "client/client.h"
+#include "client/renderingengine.h"
+#include "client/shader.h"
+#endif
 
 // garbage collector
 int LuaItemStack::gc_object(lua_State *L)
@@ -38,6 +43,15 @@ int LuaItemStack::gc_object(lua_State *L)
        return 0;
 }
 
+// __tostring metamethod
+int LuaItemStack::mt_tostring(lua_State *L)
+{
+       LuaItemStack *o = checkobject(L, 1);
+       std::string itemstring = o->m_stack.getItemString(false);
+       lua_pushfstring(L, "ItemStack(\"%s\")", itemstring.c_str());
+       return 1;
+}
+
 // is_empty(self) -> true/false
 int LuaItemStack::l_is_empty(lua_State *L)
 {
@@ -185,6 +199,16 @@ int LuaItemStack::l_get_description(lua_State *L)
        return 1;
 }
 
+// get_short_description(self)
+int LuaItemStack::l_get_short_description(lua_State *L)
+{
+       NO_MAP_LOCK_REQUIRED;
+       LuaItemStack *o = checkobject(L, 1);
+       std::string desc = o->m_stack.getShortDescription(getGameDef(L)->idef());
+       lua_pushstring(L, desc.c_str());
+       return 1;
+}
+
 // clear(self) -> true
 int LuaItemStack::l_clear(lua_State *L)
 {
@@ -423,6 +447,7 @@ int LuaItemStack::create_object(lua_State *L)
        lua_setmetatable(L, -2);
        return 1;
 }
+
 // Not callable from Lua
 int LuaItemStack::create(lua_State *L, const ItemStack &item)
 {
@@ -434,12 +459,23 @@ int LuaItemStack::create(lua_State *L, const ItemStack &item)
        return 1;
 }
 
-LuaItemStack* LuaItemStack::checkobject(lua_State *L, int narg)
+LuaItemStack *LuaItemStack::checkobject(lua_State *L, int narg)
+{
+       return *(LuaItemStack **)luaL_checkudata(L, narg, className);
+}
+
+void *LuaItemStack::packIn(lua_State *L, int idx)
 {
-       luaL_checktype(L, narg, LUA_TUSERDATA);
-       void *ud = luaL_checkudata(L, narg, className);
-       if(!ud) luaL_typerror(L, narg, className);
-       return *(LuaItemStack**)ud;  // unbox pointer
+       LuaItemStack *o = checkobject(L, idx);
+       return new ItemStack(o->getItem());
+}
+
+void LuaItemStack::packOut(lua_State *L, void *ptr)
+{
+       ItemStack *stack = reinterpret_cast<ItemStack*>(ptr);
+       if (L)
+               create(L, *stack);
+       delete stack;
 }
 
 void LuaItemStack::Register(lua_State *L)
@@ -449,9 +485,10 @@ void LuaItemStack::Register(lua_State *L)
        luaL_newmetatable(L, className);
        int metatable = lua_gettop(L);
 
+       // hide metatable from Lua getmetatable()
        lua_pushliteral(L, "__metatable");
        lua_pushvalue(L, methodtable);
-       lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
+       lua_settable(L, metatable);
 
        lua_pushliteral(L, "__index");
        lua_pushvalue(L, methodtable);
@@ -461,13 +498,19 @@ void LuaItemStack::Register(lua_State *L)
        lua_pushcfunction(L, gc_object);
        lua_settable(L, metatable);
 
+       lua_pushliteral(L, "__tostring");
+       lua_pushcfunction(L, mt_tostring);
+       lua_settable(L, metatable);
+
        lua_pop(L, 1);  // drop metatable
 
-       luaL_openlib(L, 0, methods, 0);  // fill methodtable
+       luaL_register(L, nullptr, methods);  // fill methodtable
        lua_pop(L, 1);  // drop methodtable
 
-       // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil))
+       // Can be created from Lua (ItemStack(itemstack or itemstring or table or nil))
        lua_register(L, className, create_object);
+
+       script_register_packer(L, className, packIn, packOut);
 }
 
 const char LuaItemStack::className[] = "ItemStack";
@@ -483,6 +526,7 @@ const luaL_Reg LuaItemStack::methods[] = {
        luamethod(LuaItemStack, get_metadata),
        luamethod(LuaItemStack, set_metadata),
        luamethod(LuaItemStack, get_description),
+       luamethod(LuaItemStack, get_short_description),
        luamethod(LuaItemStack, clear),
        luamethod(LuaItemStack, replace),
        luamethod(LuaItemStack, to_string),
@@ -513,16 +557,15 @@ int ModApiItemMod::l_register_item_raw(lua_State *L)
 
        // Get the writable item and node definition managers from the server
        IWritableItemDefManager *idef =
-                       getServer(L)->getWritableItemDefManager();
+                       getGameDef(L)->getWritableItemDefManager();
        NodeDefManager *ndef =
-                       getServer(L)->getWritableNodeDefManager();
+                       getGameDef(L)->getWritableNodeDefManager();
 
        // Check if name is defined
        std::string name;
        lua_getfield(L, table, "name");
        if(lua_isstring(L, -1)){
                name = readParam<std::string>(L, -1);
-               verbosestream<<"register_item_raw: "<<name<<std::endl;
        } else {
                throw LuaError("register_item_raw: name is not defined or not a string");
        }
@@ -550,11 +593,15 @@ int ModApiItemMod::l_register_item_raw(lua_State *L)
 
        // Read the node definition (content features) and register it
        if (def.type == ITEM_NODE) {
-               ContentFeatures f = read_content_features(L, table);
+               ContentFeatures f;
+               read_content_features(L, f, table);
                // when a mod reregisters ignore, only texture changes and such should
                // be done
                if (f.name == "ignore")
                        return 0;
+               // This would break everything
+               if (f.name.empty())
+                       throw LuaError("Cannot register node with empty name");
 
                content_t id = ndef->set(f.name, f);
 
@@ -563,8 +610,9 @@ int ModApiItemMod::l_register_item_raw(lua_State *L)
                                        + itos(MAX_REGISTERED_CONTENT+1)
                                        + ") exceeded (" + name + ")");
                }
+               
        }
-
+       
        return 0; /* number of results */
 }
 
@@ -575,12 +623,12 @@ int ModApiItemMod::l_unregister_item_raw(lua_State *L)
        std::string name = luaL_checkstring(L, 1);
 
        IWritableItemDefManager *idef =
-                       getServer(L)->getWritableItemDefManager();
+                       getGameDef(L)->getWritableItemDefManager();
 
        // Unregister the node
        if (idef->get(name).type == ITEM_NODE) {
                NodeDefManager *ndef =
-                       getServer(L)->getWritableNodeDefManager();
+                       getGameDef(L)->getWritableNodeDefManager();
                ndef->removeNode(name);
        }
 
@@ -598,7 +646,7 @@ int ModApiItemMod::l_register_alias_raw(lua_State *L)
 
        // Get the writable item definition manager from the server
        IWritableItemDefManager *idef =
-                       getServer(L)->getWritableItemDefManager();
+                       getGameDef(L)->getWritableItemDefManager();
 
        idef->registerAlias(name, convert_to);
 
@@ -611,10 +659,21 @@ int ModApiItemMod::l_get_content_id(lua_State *L)
        NO_MAP_LOCK_REQUIRED;
        std::string name = luaL_checkstring(L, 1);
 
-       const NodeDefManager *ndef = getGameDef(L)->getNodeDefManager();
+       const IItemDefManager *idef = getGameDef(L)->idef();
+       const NodeDefManager *ndef = getGameDef(L)->ndef();
+
+       // If this is called at mod load time, NodeDefManager isn't aware of
+       // aliases yet, so we need to handle them manually
+       std::string alias_name = idef->getAlias(name);
+
        content_t content_id;
-       if (!ndef->getId(name, content_id))
+       if (alias_name != name) {
+               if (!ndef->getId(alias_name, content_id))
+                       throw LuaError("Unknown node: " + alias_name +
+                                       " (from alias " + name + ")");
+       } else if (!ndef->getId(name, content_id)) {
                throw LuaError("Unknown node: " + name);
+       }
 
        lua_pushinteger(L, content_id);
        return 1; /* number of results */
@@ -626,7 +685,7 @@ int ModApiItemMod::l_get_name_from_content_id(lua_State *L)
        NO_MAP_LOCK_REQUIRED;
        content_t c = luaL_checkint(L, 1);
 
-       const NodeDefManager *ndef = getGameDef(L)->getNodeDefManager();
+       const NodeDefManager *ndef = getGameDef(L)->ndef();
        const char *name = ndef->get(c).name.c_str();
 
        lua_pushstring(L, name);
@@ -641,3 +700,10 @@ void ModApiItemMod::Initialize(lua_State *L, int top)
        API_FCT(get_content_id);
        API_FCT(get_name_from_content_id);
 }
+
+void ModApiItemMod::InitializeAsync(lua_State *L, int top)
+{
+       // all read-only functions
+       API_FCT(get_content_id);
+       API_FCT(get_name_from_content_id);
+}