ToolDefManager serialization
[oweals/minetest.git] / src / inventory.cpp
index 92ef3b011f708c5fbb744d90355b3172093c9919..8ddbd3ac8add37e1ad0e83b170ee76a357a3fddf 100644 (file)
@@ -1,6 +1,6 @@
 /*
 Minetest-c55
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -17,30 +17,31 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-/*
-(c) 2010 Perttu Ahola <celeron55@gmail.com>
-*/
-
 #include "inventory.h"
 #include "serialization.h"
 #include "utility.h"
 #include "debug.h"
 #include <sstream>
-#include "main.h"
+#include "main.h" // For tsrc, g_toolmanager
 #include "serverobject.h"
 #include "content_mapnode.h"
 #include "content_inventory.h"
 #include "content_sao.h"
 #include "player.h"
 #include "log.h"
+#include "nodedef.h"
+#include "tooldef.h"
+#include "gamedef.h"
 
 /*
        InventoryItem
 */
 
-InventoryItem::InventoryItem(u16 count)
+InventoryItem::InventoryItem(IGameDef *gamedef, u16 count):
+       m_gamedef(gamedef),
+       m_count(count)
 {
-       m_count = count;
+       assert(m_gamedef);
 }
 
 InventoryItem::~InventoryItem()
@@ -59,7 +60,7 @@ content_t content_translate_from_19_to_internal(content_t c_from)
        return c_from;
 }
 
-InventoryItem* InventoryItem::deSerialize(std::istream &is)
+InventoryItem* InventoryItem::deSerialize(std::istream &is, IGameDef *gamedef)
 {
        DSTACK(__FUNCTION_NAME);
 
@@ -82,7 +83,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
                }
                if(material > MAX_CONTENT)
                        throw SerializationError("Too large material number");
-               return new MaterialItem(material, count);
+               return new MaterialItem(gamedef, material, count);
        }
        else if(name == "MaterialItem2")
        {
@@ -92,7 +93,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
                is>>count;
                if(material > MAX_CONTENT)
                        throw SerializationError("Too large material number");
-               return new MaterialItem(material, count);
+               return new MaterialItem(gamedef, material, count);
        }
        else if(name == "MBOItem")
        {
@@ -106,7 +107,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
                std::getline(is, subname, ' ');
                u16 count;
                is>>count;
-               return new CraftItem(subname, count);
+               return new CraftItem(gamedef, subname, count);
        }
        else if(name == "ToolItem")
        {
@@ -114,7 +115,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
                std::getline(is, toolname, ' ');
                u16 wear;
                is>>wear;
-               return new ToolItem(toolname, wear);
+               return new ToolItem(gamedef, toolname, wear);
        }
        else
        {
@@ -135,8 +136,12 @@ ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, u16 id, v3f
        /*
                Create an ItemSAO
        */
+       pos.Y -= BS*0.25; // let it drop a bit
+       // Randomize a bit
+       pos.X += BS*0.2*(float)myrand_range(-1000,1000)/1000.0;
+       pos.Z += BS*0.2*(float)myrand_range(-1000,1000)/1000.0;
        // Create object
-       ServerActiveObject *obj = new ItemSAO(env, 0, pos, getItemString());
+       ServerActiveObject *obj = new ItemSAO(env, pos, getItemString());
        return obj;
 }
 
@@ -144,37 +149,84 @@ ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, u16 id, v3f
        MaterialItem
 */
 
+#ifndef SERVER
+video::ITexture * MaterialItem::getImage(ITextureSource *tsrc) const
+{
+       return m_gamedef->getNodeDefManager()->get(m_content).inventory_texture;
+}
+#endif
+
 bool MaterialItem::isCookable() const
 {
-       return item_material_is_cookable(m_content);
+       return item_material_is_cookable(m_content, m_gamedef);
 }
 
 InventoryItem *MaterialItem::createCookResult() const
 {
-       return item_material_create_cook_result(m_content);
+       return item_material_create_cook_result(m_content, m_gamedef);
+}
+
+/*
+       ToolItem
+*/
+
+std::string ToolItem::getImageBasename() const
+{
+       return m_gamedef->getToolDefManager()->getImagename(m_toolname);
+}
+
+#ifndef SERVER
+video::ITexture * ToolItem::getImage(ITextureSource *tsrc) const
+{
+       if(tsrc == NULL)
+               return NULL;
+       
+       std::string basename = getImageBasename();
+       
+       /*
+               Calculate a progress value with sane amount of
+               maximum states
+       */
+       u32 maxprogress = 30;
+       u32 toolprogress = (65535-m_wear)/(65535/maxprogress);
+       
+       float value_f = (float)toolprogress / (float)maxprogress;
+       std::ostringstream os;
+       os<<basename<<"^[progressbar"<<value_f;
+
+       return tsrc->getTextureRaw(os.str());
+}
+
+video::ITexture * ToolItem::getImageRaw(ITextureSource *tsrc) const
+{
+       if(tsrc == NULL)
+               return NULL;
+       
+       return tsrc->getTextureRaw(getImageBasename());
 }
+#endif
 
 /*
        CraftItem
 */
 
 #ifndef SERVER
-video::ITexture * CraftItem::getImage() const
+video::ITexture * CraftItem::getImage(ITextureSource *tsrc) const
 {
-       if(g_texturesource == NULL)
+       if(tsrc == NULL)
                return NULL;
        
-       std::string name = item_craft_get_image_name(m_subname);
+       std::string name = item_craft_get_image_name(m_subname, m_gamedef);
 
        // Get such a texture
-       return g_texturesource->getTextureRaw(name);
+       return tsrc->getTextureRaw(name);
 }
 #endif
 
 ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos)
 {
        // Special cases
-       ServerActiveObject *obj = item_craft_create_object(m_subname, env, id, pos);
+       ServerActiveObject *obj = item_craft_create_object(m_subname, env, pos);
        if(obj)
                return obj;
        // Default
@@ -184,7 +236,7 @@ ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos
 u16 CraftItem::getDropCount() const
 {
        // Special cases
-       s16 dc = item_craft_get_drop_count(m_subname);
+       s16 dc = item_craft_get_drop_count(m_subname, m_gamedef);
        if(dc != -1)
                return dc;
        // Default
@@ -193,30 +245,31 @@ u16 CraftItem::getDropCount() const
 
 bool CraftItem::isCookable() const
 {
-       return item_craft_is_cookable(m_subname);
+       return item_craft_is_cookable(m_subname, m_gamedef);
 }
 
 InventoryItem *CraftItem::createCookResult() const
 {
-       return item_craft_create_cook_result(m_subname);
+       return item_craft_create_cook_result(m_subname, m_gamedef);
 }
 
-bool CraftItem::use(ServerEnvironment *env, Player *player)
+bool CraftItem::use(ServerEnvironment *env, ServerActiveObject *user)
 {
-       if(item_craft_is_eatable(m_subname))
-       {
-               u16 result_count = getCount() - 1; // Eat one at a time
-               s16 hp_change = item_craft_eat_hp_change(m_subname);
-               if(player->hp + hp_change > 20)
-                       player->hp = 20;
-               else
-                       player->hp += hp_change;
+       if(!item_craft_is_eatable(m_subname, m_gamedef))
+               return false;
+       
+       u16 result_count = getCount() - 1; // Eat one at a time
+       s16 hp_change = item_craft_eat_hp_change(m_subname, m_gamedef);
+       s16 hp = user->getHP();
+       hp += hp_change;
+       if(hp < 0)
+               hp = 0;
+       user->setHP(hp);
+       
+       if(result_count < 1)
+               return true;
                
-               if(result_count < 1)
-                       return true;
-               else
-                       setCount(result_count);
-       }
+       setCount(result_count);
        return false;
 }
 
@@ -281,7 +334,7 @@ void InventoryList::serialize(std::ostream &os) const
        os<<"EndInventoryList\n";
 }
 
-void InventoryList::deSerialize(std::istream &is)
+void InventoryList::deSerialize(std::istream &is, IGameDef *gamedef)
 {
        //is.imbue(std::locale("C"));
 
@@ -312,7 +365,7 @@ void InventoryList::deSerialize(std::istream &is)
                {
                        if(item_i > getSize() - 1)
                                throw SerializationError("too many items");
-                       InventoryItem *item = InventoryItem::deSerialize(iss);
+                       InventoryItem *item = InventoryItem::deSerialize(iss, gamedef);
                        m_items[item_i++] = item;
                }
                else if(name == "Empty")
@@ -632,7 +685,7 @@ void Inventory::serialize(std::ostream &os) const
        os<<"EndInventory\n";
 }
 
-void Inventory::deSerialize(std::istream &is)
+void Inventory::deSerialize(std::istream &is, IGameDef *gamedef)
 {
        clear();
 
@@ -664,7 +717,7 @@ void Inventory::deSerialize(std::istream &is)
                        iss>>listsize;
 
                        InventoryList *list = new InventoryList(listname, listsize);
-                       list->deSerialize(is);
+                       list->deSerialize(is, gamedef);
 
                        m_lists.push_back(list);
                }