Advertisement
Guest User

Untitled

a guest
Jul 26th, 2012
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.21 KB | None | 0 0
  1. /*
  2. Minetest-c55
  3. Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. Copyright (C) 2011 Kahrl <kahrl@gmx.net>
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU Lesser General Public License as published by
  8. the Free Software Foundation; either version 2.1 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU Lesser General Public License for more details.
  15.  
  16. You should have received a copy of the GNU Lesser General Public License along
  17. with this program; if not, write to the Free Software Foundation, Inc.,
  18. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. */
  20.  
  21. #include "itemdef.h"
  22.  
  23. #include "base64.h"
  24. #include "gamedef.h"
  25. #include "nodedef.h"
  26. #include "tool.h"
  27. #include "inventory.h"
  28. #ifndef SERVER
  29. #include "mapblock_mesh.h"
  30. #include "mesh.h"
  31. #include "tile.h"
  32. #endif
  33. #include "log.h"
  34. #include "util/serialize.h"
  35. #include <map>
  36. #include <set>
  37.  
  38. /*
  39.     ItemDefinition
  40. */
  41. ItemDefinition::ItemDefinition()
  42. {
  43.     resetInitial();
  44. }
  45.  
  46. ItemDefinition::ItemDefinition(const ItemDefinition &def)
  47. {
  48.     resetInitial();
  49.     *this = def;
  50. }
  51.  
  52. ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
  53. {
  54.     if(this == &def)
  55.         return *this;
  56.  
  57.     reset();
  58.  
  59.     type = def.type;
  60.     name = def.name;
  61.     description = def.description;
  62.     inventory_image = def.inventory_image;
  63.     wield_image = def.wield_image;
  64.     wield_scale = def.wield_scale;
  65.     stack_max = def.stack_max;
  66.     usable = def.usable;
  67.     liquids_pointable = def.liquids_pointable;
  68.     if(def.tool_capabilities)
  69.     {
  70.         tool_capabilities = new ToolCapabilities(
  71.                 *def.tool_capabilities);
  72.     }
  73.     groups = def.groups;
  74.     node_placement_prediction = def.node_placement_prediction;
  75. #ifndef SERVER
  76.     inventory_texture = def.inventory_texture;
  77.     if(def.wield_mesh)
  78.     {
  79.         wield_mesh = def.wield_mesh;
  80.         wield_mesh->grab();
  81.     }
  82. #endif
  83.     return *this;
  84. }
  85.  
  86. ItemDefinition::~ItemDefinition()
  87. {
  88.     reset();
  89. }
  90.  
  91. void ItemDefinition::resetInitial()
  92. {
  93.     // Initialize pointers to NULL so reset() does not delete undefined pointers
  94.     tool_capabilities = NULL;
  95. #ifndef SERVER
  96.     inventory_texture = NULL;
  97.     wield_mesh = NULL;
  98. #endif
  99.     reset();
  100. }
  101.  
  102. void ItemDefinition::reset()
  103. {
  104.     type = ITEM_NONE;
  105.     name = "";
  106.     description = "";
  107.     inventory_image = "";
  108.     wield_image = "";
  109.     wield_scale = v3f(1.0, 1.0, 1.0);
  110.     stack_max = 99;
  111.     usable = false;
  112.     liquids_pointable = false;
  113.     if(tool_capabilities)
  114.     {
  115.         delete tool_capabilities;
  116.         tool_capabilities = NULL;
  117.     }
  118.     groups.clear();
  119.  
  120.     node_placement_prediction = "";
  121.    
  122. #ifndef SERVER
  123.     inventory_texture = NULL;
  124.     if(wield_mesh)
  125.     {
  126.         wield_mesh->drop();
  127.         wield_mesh = NULL;
  128.     }
  129. #endif
  130. }
  131.  
  132. void ItemDefinition::serialize(std::ostream &os) const
  133. {
  134.     writeU8(os, 1); // version
  135.     writeU8(os, type);
  136.     os<<serializeString(name);
  137.     os<<serializeString(description);
  138.     os<<serializeString(inventory_image);
  139.     os<<serializeString(wield_image);
  140.     writeV3F1000(os, wield_scale);
  141.     writeS16(os, stack_max);
  142.     writeU8(os, usable);
  143.     writeU8(os, liquids_pointable);
  144.     std::string tool_capabilities_s = "";
  145.     if(tool_capabilities){
  146.         std::ostringstream tmp_os(std::ios::binary);
  147.         tool_capabilities->serialize(tmp_os);
  148.         tool_capabilities_s = tmp_os.str();
  149.     }
  150.     os<<serializeString(tool_capabilities_s);
  151.     writeU16(os, groups.size());
  152.     for(std::map<std::string, int>::const_iterator
  153.             i = groups.begin(); i != groups.end(); i++){
  154.         os<<serializeString(i->first);
  155.         writeS16(os, i->second);
  156.     }
  157.     os<<serializeString(node_placement_prediction);
  158. }
  159.  
  160. void ItemDefinition::deSerialize(std::istream &is)
  161. {
  162.     // Reset everything
  163.     reset();
  164.  
  165.     // Deserialize
  166.     int version = readU8(is);
  167.     if(version != 1)
  168.         throw SerializationError("unsupported ItemDefinition version");
  169.     type = (enum ItemType)readU8(is);
  170.     name = deSerializeString(is);
  171.     description = deSerializeString(is);
  172.     inventory_image = deSerializeString(is);
  173.     wield_image = deSerializeString(is);
  174.     wield_scale = readV3F1000(is);
  175.     stack_max = readS16(is);
  176.     usable = readU8(is);
  177.     liquids_pointable = readU8(is);
  178.     std::string tool_capabilities_s = deSerializeString(is);
  179.     if(!tool_capabilities_s.empty())
  180.     {
  181.         std::istringstream tmp_is(tool_capabilities_s, std::ios::binary);
  182.         tool_capabilities = new ToolCapabilities;
  183.         tool_capabilities->deSerialize(tmp_is);
  184.     }
  185.     groups.clear();
  186.     u32 groups_size = readU16(is);
  187.     for(u32 i=0; i<groups_size; i++){
  188.         std::string name = deSerializeString(is);
  189.         int value = readS16(is);
  190.         groups[name] = value;
  191.     }
  192.     // If you add anything here, insert it primarily inside the try-catch
  193.     // block to not need to increase the version.
  194.     try{
  195.         node_placement_prediction = deSerializeString(is);
  196.     }catch(SerializationError &e) {};
  197. }
  198.  
  199. /*
  200.     CItemDefManager
  201. */
  202.  
  203. // SUGG: Support chains of aliases?
  204.  
  205. class CItemDefManager: public IWritableItemDefManager
  206. {
  207. public:
  208.     CItemDefManager()
  209.     {
  210.         clear();
  211.     }
  212.     virtual ~CItemDefManager()
  213.     {
  214.     }
  215.     virtual const ItemDefinition& get(const std::string &name_) const
  216.     {
  217.         // Convert name according to possible alias
  218.         std::string name = getAlias(name_);
  219.         // Get the definition
  220.         std::map<std::string, ItemDefinition*>::const_iterator i;
  221.         i = m_item_definitions.find(name);
  222.         if(i == m_item_definitions.end())
  223.             i = m_item_definitions.find("unknown");
  224.         assert(i != m_item_definitions.end());
  225.         return *(i->second);
  226.     }
  227.     virtual std::string getAlias(const std::string &name) const
  228.     {
  229.         std::map<std::string, std::string>::const_iterator i;
  230.         i = m_aliases.find(name);
  231.         if(i != m_aliases.end())
  232.             return i->second;
  233.         return name;
  234.     }
  235.     virtual std::set<std::string> getAll() const
  236.     {
  237.         std::set<std::string> result;
  238.         for(std::map<std::string, ItemDefinition*>::const_iterator
  239.                 i = m_item_definitions.begin();
  240.                 i != m_item_definitions.end(); i++)
  241.         {
  242.             result.insert(i->first);
  243.         }
  244.         for(std::map<std::string, std::string>::const_iterator
  245.                 i = m_aliases.begin();
  246.                 i != m_aliases.end(); i++)
  247.         {
  248.             result.insert(i->first);
  249.         }
  250.         return result;
  251.     }
  252.     virtual bool isKnown(const std::string &name_) const
  253.     {
  254.         // Convert name according to possible alias
  255.         std::string name = getAlias(name_);
  256.         // Get the definition
  257.         std::map<std::string, ItemDefinition*>::const_iterator i;
  258.         return m_item_definitions.find(name) != m_item_definitions.end();
  259.     }
  260.     void clear()
  261.     {
  262.         for(std::map<std::string, ItemDefinition*>::const_iterator
  263.                 i = m_item_definitions.begin();
  264.                 i != m_item_definitions.end(); i++)
  265.         {
  266.             delete i->second;
  267.         }
  268.         m_item_definitions.clear();
  269.         m_aliases.clear();
  270.  
  271.         // Add the four builtin items:
  272.         //   "" is the hand
  273.         //   "unknown" is returned whenever an undefined item is accessed
  274.         //   "air" is the air node
  275.         //   "ignore" is the ignore node
  276.  
  277.         ItemDefinition* hand_def = new ItemDefinition;
  278.         hand_def->name = "";
  279.         hand_def->wield_image = "wieldhand.png";
  280.         hand_def->tool_capabilities = new ToolCapabilities;
  281.         m_item_definitions.insert(std::make_pair("", hand_def));
  282.  
  283.         ItemDefinition* unknown_def = new ItemDefinition;
  284.         unknown_def->name = "unknown";
  285.         m_item_definitions.insert(std::make_pair("unknown", unknown_def));
  286.  
  287.         ItemDefinition* air_def = new ItemDefinition;
  288.         air_def->type = ITEM_NODE;
  289.         air_def->name = "air";
  290.         m_item_definitions.insert(std::make_pair("air", air_def));
  291.  
  292.         ItemDefinition* ignore_def = new ItemDefinition;
  293.         ignore_def->type = ITEM_NODE;
  294.         ignore_def->name = "ignore";
  295.         m_item_definitions.insert(std::make_pair("ignore", ignore_def));
  296.     }
  297.     virtual void registerItem(const ItemDefinition &def)
  298.     {
  299.         verbosestream<<"ItemDefManager: registering \""<<def.name<<"\""<<std::endl;
  300.         // Ensure that the "" item (the hand) always has ToolCapabilities
  301.         if(def.name == "")
  302.             assert(def.tool_capabilities != NULL);
  303.        
  304.         if(m_item_definitions.count(def.name) == 0)
  305.             m_item_definitions[def.name] = new ItemDefinition(def);
  306.         else
  307.             *(m_item_definitions[def.name]) = def;
  308.  
  309.         // Remove conflicting alias if it exists
  310.         bool alias_removed = (m_aliases.erase(def.name) != 0);
  311.         if(alias_removed)
  312.             infostream<<"ItemDefManager: erased alias "<<def.name
  313.                     <<" because item was defined"<<std::endl;
  314.     }
  315.     virtual void registerAlias(const std::string &name,
  316.             const std::string &convert_to)
  317.     {
  318.         if(m_item_definitions.find(name) == m_item_definitions.end())
  319.         {
  320.             verbosestream<<"ItemDefManager: setting alias "<<name
  321.                 <<" -> "<<convert_to<<std::endl;
  322.             m_aliases[name] = convert_to;
  323.         }
  324.     }
  325.  
  326.     virtual void updateTexturesAndMeshes(IGameDef *gamedef)
  327.     {
  328. #ifndef SERVER
  329.         infostream<<"ItemDefManager::updateTexturesAndMeshes(): Updating "
  330.                 <<"textures and meshes in item definitions"<<std::endl;
  331.  
  332.         ITextureSource *tsrc = gamedef->getTextureSource();
  333.         INodeDefManager *nodedef = gamedef->getNodeDefManager();
  334.         IrrlichtDevice *device = tsrc->getDevice();
  335.         video::IVideoDriver *driver = device->getVideoDriver();
  336.  
  337.         for(std::map<std::string, ItemDefinition*>::iterator
  338.                 i = m_item_definitions.begin();
  339.                 i != m_item_definitions.end(); i++)
  340.         {
  341.             ItemDefinition *def = i->second;
  342.  
  343.             bool need_node_mesh = false;
  344.  
  345.             // Create an inventory texture
  346.             def->inventory_texture = NULL;
  347.             if(def->inventory_image != "")
  348.             {
  349.                 def->inventory_texture = tsrc->getTextureRaw(def->inventory_image);
  350.             }
  351.             else if(def->type == ITEM_NODE)
  352.             {
  353.                 need_node_mesh = true;
  354.             }
  355.  
  356.             // Create a wield mesh
  357.             if(def->wield_mesh != NULL)
  358.             {
  359.                 def->wield_mesh->drop();
  360.                 def->wield_mesh = NULL;
  361.             }
  362.             if(def->type == ITEM_NODE && def->wield_image == "")
  363.             {
  364.                 need_node_mesh = true;
  365.             }
  366.             else if(def->wield_image != "" || def->inventory_image != "")
  367.             {
  368.                 // Extrude the wield image into a mesh
  369.  
  370.                 std::string imagename;
  371.                 if(def->wield_image != "")
  372.                     imagename = def->wield_image;
  373.                 else
  374.                     imagename = def->inventory_image;
  375.  
  376.                 def->wield_mesh = createExtrudedMesh(
  377.                         tsrc->getTextureRaw(imagename),
  378.                         driver,
  379.                         def->wield_scale * v3f(40.0, 40.0, 4.0));
  380.                 if(def->wield_mesh == NULL)
  381.                 {
  382.                     infostream<<"ItemDefManager: WARNING: "
  383.                         <<"updateTexturesAndMeshes(): "
  384.                         <<"Unable to create extruded mesh for item "
  385.                         <<def->name<<std::endl;
  386.                 }
  387.             }
  388.  
  389.             if(need_node_mesh)
  390.             {
  391.                 /*
  392.                     Get node properties
  393.                 */
  394.                 content_t id = nodedef->getId(def->name);
  395.                 const ContentFeatures &f = nodedef->get(id);
  396.  
  397.                 u8 param1 = 0;
  398.                 if(f.param_type == CPT_LIGHT)
  399.                     param1 = 0xee;
  400.  
  401.                 /*
  402.                     Make a mesh from the node
  403.                 */
  404.                 MeshMakeData mesh_make_data(gamedef);
  405.                 MapNode mesh_make_node(id, param1, 0);
  406.                 mesh_make_data.fillSingleNode(&mesh_make_node);
  407.                 MapBlockMesh mapblock_mesh(&mesh_make_data);
  408.  
  409.                 scene::IMesh *node_mesh = mapblock_mesh.getMesh();
  410.                 assert(node_mesh);
  411.                 setMeshColor(node_mesh, video::SColor(255, 255, 255, 255));
  412.  
  413.                 /*
  414.                     Scale and translate the mesh so it's a unit cube
  415.                     centered on the origin
  416.                 */
  417.                 scaleMesh(node_mesh, v3f(1.0/BS, 1.0/BS, 1.0/BS));
  418.                 translateMesh(node_mesh, v3f(-1.0, -1.0, -1.0));
  419.  
  420.                 /*
  421.                     Draw node mesh into a render target texture
  422.                 */
  423.                 if(def->inventory_texture == NULL)
  424.                 {
  425.                     core::dimension2d<u32> dim(64,64);
  426.                     std::string rtt_texture_name = "INVENTORY_"
  427.                         + def->name + "_RTT";
  428.                     v3f camera_position(0, 1.0, -1.5);
  429.                     camera_position.rotateXZBy(45);
  430.                     v3f camera_lookat(0, 0, 0);
  431.                     core::CMatrix4<f32> camera_projection_matrix;
  432.                     // Set orthogonal projection
  433.                     camera_projection_matrix.buildProjectionMatrixOrthoLH(
  434.                             1.65, 1.65, 0, 100);
  435.  
  436.                     video::SColorf ambient_light(0.2,0.2,0.2);
  437.                     v3f light_position(10, 100, -50);
  438.                     video::SColorf light_color(0.5,0.5,0.5);
  439.                     f32 light_radius = 1000;
  440.  
  441.                     def->inventory_texture = generateTextureFromMesh(
  442.                         node_mesh, device, dim, rtt_texture_name,
  443.                         camera_position,
  444.                         camera_lookat,
  445.                         camera_projection_matrix,
  446.                         ambient_light,
  447.                         light_position,
  448.                         light_color,
  449.                         light_radius);
  450.  
  451.                     // render-to-target didn't work
  452.                     if(def->inventory_texture == NULL)
  453.                     {
  454.                         def->inventory_texture =
  455.                             tsrc->getTextureRaw(f.tiledef[0].name);
  456.                     }
  457.  
  458.                     // BEGIN WIKI IMAGE EXTRACT
  459.                     infostream<<"WIKI IMAGE EXTRACT: def->name = '"<<def->name<<"'"<<std::endl;
  460.                     if (def->inventory_texture != NULL) {
  461.                         video::IImage* wiki_image = driver->createImageFromData (
  462.                           def->inventory_texture->getColorFormat(),
  463.                           def->inventory_texture->getSize(),
  464.                           def->inventory_texture->lock(),
  465.                           false  //copy mem
  466.                           );
  467.                         def->inventory_texture->unlock();
  468.                         if(wiki_image != NULL) {
  469.  
  470.                             //std::string se = def->name;
  471.                             //for (int i = 0; i < se.length(); ++i)  if (se[i] == ':') se[i] = '_';
  472.                             std::string se = base64_encode(reinterpret_cast<const unsigned char*>(def->name.c_str()), def->name.length());
  473.  
  474.                             irr::c8 filename[1024];
  475.                             snprintf(filename, 1024, "wikiimage/%s.png", se); // this fails after about the 14th image
  476.                             driver->writeImageToFile(wiki_image, filename);
  477.                            
  478.                             wiki_image->drop();
  479.                         }
  480.                     }
  481.                     // END WIKI IMAGE EXTRACT
  482.  
  483.                 }
  484.  
  485.                 /*
  486.                     Use the node mesh as the wield mesh
  487.                 */
  488.                 if(def->wield_mesh == NULL)
  489.                 {
  490.                     // Scale to proper wield mesh proportions
  491.                     scaleMesh(node_mesh, v3f(30.0, 30.0, 30.0)
  492.                             * def->wield_scale);
  493.                     def->wield_mesh = node_mesh;
  494.                     def->wield_mesh->grab();
  495.                 }
  496.  
  497.                 // falling outside of here deletes node_mesh
  498.             }
  499.         }
  500. #endif
  501.     }
  502.     void serialize(std::ostream &os)
  503.     {
  504.         writeU8(os, 0); // version
  505.         u16 count = m_item_definitions.size();
  506.         writeU16(os, count);
  507.         for(std::map<std::string, ItemDefinition*>::const_iterator
  508.                 i = m_item_definitions.begin();
  509.                 i != m_item_definitions.end(); i++)
  510.         {
  511.             ItemDefinition *def = i->second;
  512.             // Serialize ItemDefinition and write wrapped in a string
  513.             std::ostringstream tmp_os(std::ios::binary);
  514.             def->serialize(tmp_os);
  515.             os<<serializeString(tmp_os.str());
  516.         }
  517.         writeU16(os, m_aliases.size());
  518.         for(std::map<std::string, std::string>::const_iterator
  519.             i = m_aliases.begin(); i != m_aliases.end(); i++)
  520.         {
  521.             os<<serializeString(i->first);
  522.             os<<serializeString(i->second);
  523.         }
  524.     }
  525.     void deSerialize(std::istream &is)
  526.     {
  527.         // Clear everything
  528.         clear();
  529.         // Deserialize
  530.         int version = readU8(is);
  531.         if(version != 0)
  532.             throw SerializationError("unsupported ItemDefManager version");
  533.         u16 count = readU16(is);
  534.         for(u16 i=0; i<count; i++)
  535.         {
  536.             // Deserialize a string and grab an ItemDefinition from it
  537.             std::istringstream tmp_is(deSerializeString(is), std::ios::binary);
  538.             ItemDefinition def;
  539.             def.deSerialize(tmp_is);
  540.             // Register
  541.             registerItem(def);
  542.         }
  543.         u16 num_aliases = readU16(is);
  544.         for(u16 i=0; i<num_aliases; i++)
  545.         {
  546.             std::string name = deSerializeString(is);
  547.             std::string convert_to = deSerializeString(is);
  548.             registerAlias(name, convert_to);
  549.         }
  550.     }
  551. private:
  552.     // Key is name
  553.     std::map<std::string, ItemDefinition*> m_item_definitions;
  554.     // Aliases
  555.     std::map<std::string, std::string> m_aliases;
  556. };
  557.  
  558. IWritableItemDefManager* createItemDefManager()
  559. {
  560.     return new CItemDefManager();
  561. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement