Advertisement
Guest User

Untitled

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