LCOV - code coverage report
Current view: top level - src - itemdef.cpp (source / functions) Hit Total Coverage
Test: report Lines: 260 351 74.1 %
Date: 2015-07-11 18:23:49 Functions: 25 29 86.2 %

          Line data    Source code
       1             : /*
       2             : Minetest
       3             : Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
       4             : Copyright (C) 2013 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 "gamedef.h"
      24             : #include "nodedef.h"
      25             : #include "tool.h"
      26             : #include "inventory.h"
      27             : #ifndef SERVER
      28             : #include "mapblock_mesh.h"
      29             : #include "mesh.h"
      30             : #include "wieldmesh.h"
      31             : #include "client/tile.h"
      32             : #endif
      33             : #include "log.h"
      34             : #include "settings.h"
      35             : #include "util/serialize.h"
      36             : #include "util/container.h"
      37             : #include "util/thread.h"
      38             : #include <map>
      39             : #include <set>
      40             : 
      41             : #ifdef __ANDROID__
      42             : #include <GLES/gl.h>
      43             : #endif
      44             : 
      45             : /*
      46             :         ItemDefinition
      47             : */
      48        5508 : ItemDefinition::ItemDefinition()
      49             : {
      50        5508 :         resetInitial();
      51        5508 : }
      52             : 
      53        5496 : ItemDefinition::ItemDefinition(const ItemDefinition &def)
      54             : {
      55        5496 :         resetInitial();
      56        5496 :         *this = def;
      57        5496 : }
      58             : 
      59        5500 : ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
      60             : {
      61        5500 :         if(this == &def)
      62           0 :                 return *this;
      63             : 
      64        5500 :         reset();
      65             : 
      66        5500 :         type = def.type;
      67        5500 :         name = def.name;
      68        5500 :         description = def.description;
      69        5500 :         inventory_image = def.inventory_image;
      70        5500 :         wield_image = def.wield_image;
      71        5500 :         wield_scale = def.wield_scale;
      72        5500 :         stack_max = def.stack_max;
      73        5500 :         usable = def.usable;
      74        5500 :         liquids_pointable = def.liquids_pointable;
      75        5500 :         if(def.tool_capabilities)
      76             :         {
      77             :                 tool_capabilities = new ToolCapabilities(
      78          42 :                                 *def.tool_capabilities);
      79             :         }
      80        5500 :         groups = def.groups;
      81        5500 :         node_placement_prediction = def.node_placement_prediction;
      82        5500 :         sound_place = def.sound_place;
      83        5500 :         range = def.range;
      84        5500 :         return *this;
      85             : }
      86             : 
      87       22008 : ItemDefinition::~ItemDefinition()
      88             : {
      89       11004 :         reset();
      90       11004 : }
      91             : 
      92       11004 : void ItemDefinition::resetInitial()
      93             : {
      94             :         // Initialize pointers to NULL so reset() does not delete undefined pointers
      95       11004 :         tool_capabilities = NULL;
      96       11004 :         reset();
      97       11004 : }
      98             : 
      99       33008 : void ItemDefinition::reset()
     100             : {
     101       33008 :         type = ITEM_NONE;
     102       33008 :         name = "";
     103       33008 :         description = "";
     104       33008 :         inventory_image = "";
     105       33008 :         wield_image = "";
     106       33008 :         wield_scale = v3f(1.0, 1.0, 1.0);
     107       33008 :         stack_max = 99;
     108       33008 :         usable = false;
     109       33008 :         liquids_pointable = false;
     110       33008 :         if(tool_capabilities)
     111             :         {
     112          86 :                 delete tool_capabilities;
     113          86 :                 tool_capabilities = NULL;
     114             :         }
     115       33008 :         groups.clear();
     116       33008 :         sound_place = SimpleSoundSpec();
     117       33008 :         range = -1;
     118             : 
     119       33008 :         node_placement_prediction = "";
     120       33008 : }
     121             : 
     122           0 : void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
     123             : {
     124           0 :         if(protocol_version <= 17)
     125           0 :                 writeU8(os, 1); // version
     126           0 :         else if(protocol_version <= 20)
     127           0 :                 writeU8(os, 2); // version
     128             :         else
     129           0 :                 writeU8(os, 3); // version
     130           0 :         writeU8(os, type);
     131           0 :         os<<serializeString(name);
     132           0 :         os<<serializeString(description);
     133           0 :         os<<serializeString(inventory_image);
     134           0 :         os<<serializeString(wield_image);
     135           0 :         writeV3F1000(os, wield_scale);
     136           0 :         writeS16(os, stack_max);
     137           0 :         writeU8(os, usable);
     138           0 :         writeU8(os, liquids_pointable);
     139           0 :         std::string tool_capabilities_s = "";
     140           0 :         if(tool_capabilities){
     141           0 :                 std::ostringstream tmp_os(std::ios::binary);
     142           0 :                 tool_capabilities->serialize(tmp_os, protocol_version);
     143           0 :                 tool_capabilities_s = tmp_os.str();
     144             :         }
     145           0 :         os<<serializeString(tool_capabilities_s);
     146           0 :         writeU16(os, groups.size());
     147           0 :         for(std::map<std::string, int>::const_iterator
     148           0 :                         i = groups.begin(); i != groups.end(); i++){
     149           0 :                 os<<serializeString(i->first);
     150           0 :                 writeS16(os, i->second);
     151             :         }
     152           0 :         os<<serializeString(node_placement_prediction);
     153           0 :         if(protocol_version > 17){
     154             :                 //serializeSimpleSoundSpec(sound_place, os);
     155           0 :                 os<<serializeString(sound_place.name);
     156           0 :                 writeF1000(os, sound_place.gain);
     157             :         }
     158           0 :         if(protocol_version > 20){
     159           0 :                 writeF1000(os, range);
     160             :         }
     161           0 : }
     162             : 
     163        5500 : void ItemDefinition::deSerialize(std::istream &is)
     164             : {
     165             :         // Reset everything
     166        5500 :         reset();
     167             : 
     168             :         // Deserialize
     169        5500 :         int version = readU8(is);
     170        5500 :         if(version < 1 || version > 3)
     171           0 :                 throw SerializationError("unsupported ItemDefinition version");
     172        5500 :         type = (enum ItemType)readU8(is);
     173        5500 :         name = deSerializeString(is);
     174        5500 :         description = deSerializeString(is);
     175        5500 :         inventory_image = deSerializeString(is);
     176        5500 :         wield_image = deSerializeString(is);
     177        5500 :         wield_scale = readV3F1000(is);
     178        5500 :         stack_max = readS16(is);
     179        5500 :         usable = readU8(is);
     180        5500 :         liquids_pointable = readU8(is);
     181       11000 :         std::string tool_capabilities_s = deSerializeString(is);
     182        5500 :         if(!tool_capabilities_s.empty())
     183             :         {
     184          84 :                 std::istringstream tmp_is(tool_capabilities_s, std::ios::binary);
     185          42 :                 tool_capabilities = new ToolCapabilities;
     186          42 :                 tool_capabilities->deSerialize(tmp_is);
     187             :         }
     188        5500 :         groups.clear();
     189        5500 :         u32 groups_size = readU16(is);
     190       22766 :         for(u32 i=0; i<groups_size; i++){
     191       34532 :                 std::string name = deSerializeString(is);
     192       17266 :                 int value = readS16(is);
     193       17266 :                 groups[name] = value;
     194             :         }
     195        5500 :         if(version == 1){
     196             :                 // We cant be sure that node_placement_prediction is send in version 1
     197             :                 try{
     198           0 :                         node_placement_prediction = deSerializeString(is);
     199           0 :                 }catch(SerializationError &e) {};
     200             :                 // Set the old default sound
     201           0 :                 sound_place.name = "default_place_node";
     202           0 :                 sound_place.gain = 0.5;
     203        5500 :         } else if(version >= 2) {
     204        5500 :                 node_placement_prediction = deSerializeString(is);
     205             :                 //deserializeSimpleSoundSpec(sound_place, is);
     206        5500 :                 sound_place.name = deSerializeString(is);
     207        5500 :                 sound_place.gain = readF1000(is);
     208             :         }
     209        5500 :         if(version == 3) {
     210        5500 :                 range = readF1000(is);
     211             :         }
     212             :         // If you add anything here, insert it primarily inside the try-catch
     213             :         // block to not need to increase the version.
     214             :         try{
     215             :         }catch(SerializationError &e) {};
     216        5500 : }
     217             : 
     218             : /*
     219             :         CItemDefManager
     220             : */
     221             : 
     222             : // SUGG: Support chains of aliases?
     223             : 
     224             : class CItemDefManager: public IWritableItemDefManager
     225             : {
     226             : #ifndef SERVER
     227             :         struct ClientCached
     228             :         {
     229             :                 video::ITexture *inventory_texture;
     230             :                 scene::IMesh *wield_mesh;
     231             : 
     232           8 :                 ClientCached():
     233             :                         inventory_texture(NULL),
     234           8 :                         wield_mesh(NULL)
     235           8 :                 {}
     236             :         };
     237             : #endif
     238             : 
     239             : public:
     240           1 :         CItemDefManager()
     241           1 :         {
     242             : 
     243             : #ifndef SERVER
     244           1 :                 m_main_thread = get_current_thread_id();
     245             : #endif
     246           1 :                 clear();
     247           1 :         }
     248           2 :         virtual ~CItemDefManager()
     249           2 :         {
     250             : #ifndef SERVER
     251           2 :                 const std::vector<ClientCached*> &values = m_clientcached.getValues();
     252          23 :                 for(std::vector<ClientCached*>::const_iterator
     253           9 :                                 i = values.begin(); i != values.end(); ++i)
     254             :                 {
     255           7 :                         ClientCached *cc = *i;
     256           7 :                         if (cc->wield_mesh)
     257           0 :                                 cc->wield_mesh->drop();
     258           7 :                         delete cc;
     259             :                 }
     260             : 
     261             : #endif
     262       16502 :                 for (std::map<std::string, ItemDefinition*>::iterator iter =
     263        5502 :                                 m_item_definitions.begin(); iter != m_item_definitions.end();
     264             :                                 iter ++) {
     265        5500 :                         delete iter->second;
     266             :                 }
     267           1 :                 m_item_definitions.clear();
     268           2 :         }
     269       14321 :         virtual const ItemDefinition& get(const std::string &name_) const
     270             :         {
     271             :                 // Convert name according to possible alias
     272       28642 :                 std::string name = getAlias(name_);
     273             :                 // Get the definition
     274       14321 :                 std::map<std::string, ItemDefinition*>::const_iterator i;
     275       14321 :                 i = m_item_definitions.find(name);
     276       14321 :                 if(i == m_item_definitions.end())
     277           1 :                         i = m_item_definitions.find("unknown");
     278             :                 assert(i != m_item_definitions.end());
     279       28642 :                 return *(i->second);
     280             :         }
     281       23219 :         virtual std::string getAlias(const std::string &name) const
     282             :         {
     283       23219 :                 StringMap::const_iterator it = m_aliases.find(name);
     284       23219 :                 if (it != m_aliases.end())
     285        1841 :                         return it->second;
     286       21378 :                 return name;
     287             :         }
     288           1 :         virtual std::set<std::string> getAll() const
     289             :         {
     290           1 :                 std::set<std::string> result;
     291       16502 :                 for(std::map<std::string, ItemDefinition *>::const_iterator
     292           1 :                                 it = m_item_definitions.begin();
     293       11002 :                                 it != m_item_definitions.end(); ++it) {
     294        5500 :                         result.insert(it->first);
     295             :                 }
     296        5525 :                 for (StringMap::const_iterator
     297           1 :                                 it = m_aliases.begin();
     298        3684 :                                 it != m_aliases.end(); ++it) {
     299        1841 :                         result.insert(it->first);
     300             :                 }
     301           1 :                 return result;
     302             :         }
     303           0 :         virtual bool isKnown(const std::string &name_) const
     304             :         {
     305             :                 // Convert name according to possible alias
     306           0 :                 std::string name = getAlias(name_);
     307             :                 // Get the definition
     308           0 :                 std::map<std::string, ItemDefinition*>::const_iterator i;
     309           0 :                 return m_item_definitions.find(name) != m_item_definitions.end();
     310             :         }
     311             : #ifndef SERVER
     312             : public:
     313           7 :         ClientCached* createClientCachedDirect(const std::string &name,
     314             :                         IGameDef *gamedef) const
     315             :         {
     316           7 :                 infostream<<"Lazily creating item texture and mesh for \""
     317           7 :                                 <<name<<"\""<<std::endl;
     318             : 
     319             :                 // This is not thread-safe
     320           7 :                 sanity_check(get_current_thread_id() == m_main_thread);
     321             : 
     322             :                 // Skip if already in cache
     323           7 :                 ClientCached *cc = NULL;
     324           7 :                 m_clientcached.get(name, &cc);
     325           7 :                 if(cc)
     326           0 :                         return cc;
     327             : 
     328           7 :                 ITextureSource *tsrc = gamedef->getTextureSource();
     329           7 :                 INodeDefManager *nodedef = gamedef->getNodeDefManager();
     330           7 :                 const ItemDefinition &def = get(name);
     331             : 
     332             :                 // Create new ClientCached
     333           7 :                 cc = new ClientCached();
     334             : 
     335             :                 // Create an inventory texture
     336           7 :                 cc->inventory_texture = NULL;
     337           7 :                 if(def.inventory_image != "")
     338           6 :                         cc->inventory_texture = tsrc->getTexture(def.inventory_image);
     339             : 
     340             :                 // Additional processing for nodes:
     341             :                 // - Create a wield mesh if WieldMeshSceneNode can't render
     342             :                 //   the node on its own.
     343             :                 // - If inventory_texture isn't set yet, create one using
     344             :                 //   render-to-texture.
     345           7 :                 if (def.type == ITEM_NODE) {
     346             :                         // Get node properties
     347           2 :                         content_t id = nodedef->getId(name);
     348           2 :                         const ContentFeatures &f = nodedef->get(id);
     349             : 
     350           2 :                         bool need_rtt_mesh = cc->inventory_texture == NULL;
     351             : 
     352             :                         // Keep this in sync with WieldMeshSceneNode::setItem()
     353             :                         bool need_wield_mesh =
     354           3 :                                 !(f.mesh_ptr[0] ||
     355           1 :                                   f.drawtype == NDT_NORMAL ||
     356           0 :                                   f.drawtype == NDT_ALLFACES ||
     357           2 :                                   f.drawtype == NDT_AIRLIKE);
     358             : 
     359           2 :                         scene::IMesh *node_mesh = NULL;
     360             : 
     361           2 :                         if (need_rtt_mesh || need_wield_mesh) {
     362           1 :                                 u8 param1 = 0;
     363           1 :                                 if (f.param_type == CPT_LIGHT)
     364           0 :                                         param1 = 0xee;
     365             : 
     366             :                                 /*
     367             :                                         Make a mesh from the node
     368             :                                 */
     369           2 :                                 MeshMakeData mesh_make_data(gamedef, false);
     370           1 :                                 u8 param2 = 0;
     371           1 :                                 if (f.param_type_2 == CPT2_WALLMOUNTED)
     372           0 :                                         param2 = 1;
     373           1 :                                 MapNode mesh_make_node(id, param1, param2);
     374           1 :                                 mesh_make_data.fillSingleNode(&mesh_make_node);
     375           2 :                                 MapBlockMesh mapblock_mesh(&mesh_make_data, v3s16(0, 0, 0));
     376           1 :                                 node_mesh = mapblock_mesh.getMesh();
     377           1 :                                 node_mesh->grab();
     378           1 :                                 video::SColor c(255, 255, 255, 255);
     379           1 :                                 setMeshColor(node_mesh, c);
     380             : 
     381             :                                 // scale and translate the mesh so it's a
     382             :                                 // unit cube centered on the origin
     383           1 :                                 scaleMesh(node_mesh, v3f(1.0/BS, 1.0/BS, 1.0/BS));
     384           1 :                                 translateMesh(node_mesh, v3f(-1.0, -1.0, -1.0));
     385             :                         }
     386             : 
     387             :                         /*
     388             :                                 Draw node mesh into a render target texture
     389             :                         */
     390           2 :                         if (need_rtt_mesh) {
     391           2 :                                 TextureFromMeshParams params;
     392           1 :                                 params.mesh = node_mesh;
     393           1 :                                 params.dim.set(64, 64);
     394             :                                 params.rtt_texture_name = "INVENTORY_"
     395           1 :                                         + def.name + "_RTT";
     396           1 :                                 params.delete_texture_on_shutdown = true;
     397           1 :                                 params.camera_position.set(0, 1.0, -1.5);
     398           1 :                                 params.camera_position.rotateXZBy(45);
     399           1 :                                 params.camera_lookat.set(0, 0, 0);
     400             :                                 // Set orthogonal projection
     401             :                                 params.camera_projection_matrix.buildProjectionMatrixOrthoLH(
     402           1 :                                                 1.65, 1.65, 0, 100);
     403           1 :                                 params.ambient_light.set(1.0, 0.2, 0.2, 0.2);
     404           1 :                                 params.light_position.set(10, 100, -50);
     405           1 :                                 params.light_color.set(1.0, 0.5, 0.5, 0.5);
     406           1 :                                 params.light_radius = 1000;
     407             : 
     408             : #ifdef __ANDROID__
     409             :                                 params.camera_position.set(0, -1.0, -1.5);
     410             :                                 params.camera_position.rotateXZBy(45);
     411             :                                 params.light_position.set(10, -100, -50);
     412             : #endif
     413           1 :                                 cc->inventory_texture =
     414           1 :                                         tsrc->generateTextureFromMesh(params);
     415             : 
     416             :                                 // render-to-target didn't work
     417           1 :                                 if (cc->inventory_texture == NULL) {
     418           0 :                                         cc->inventory_texture =
     419           0 :                                                 tsrc->getTexture(f.tiledef[0].name);
     420             :                                 }
     421             :                         }
     422             : 
     423             :                         /*
     424             :                                 Use the node mesh as the wield mesh
     425             :                         */
     426           2 :                         if (need_wield_mesh) {
     427           0 :                                 cc->wield_mesh = node_mesh;
     428           0 :                                 cc->wield_mesh->grab();
     429             : 
     430             :                                 // no way reference count can be smaller than 2 in this place!
     431             :                                 assert(cc->wield_mesh->getReferenceCount() >= 2);
     432             :                         }
     433             : 
     434           2 :                         if (node_mesh)
     435           1 :                                 node_mesh->drop();
     436             :                 }
     437             : 
     438             :                 // Put in cache
     439           7 :                 m_clientcached.set(name, cc);
     440             : 
     441           7 :                 return cc;
     442             :         }
     443        8162 :         ClientCached* getClientCached(const std::string &name,
     444             :                         IGameDef *gamedef) const
     445             :         {
     446        8162 :                 ClientCached *cc = NULL;
     447        8162 :                 m_clientcached.get(name, &cc);
     448        8162 :                 if(cc)
     449        8155 :                         return cc;
     450             : 
     451           7 :                 if(get_current_thread_id() == m_main_thread)
     452             :                 {
     453           7 :                         return createClientCachedDirect(name, gamedef);
     454             :                 }
     455             :                 else
     456             :                 {
     457             :                         // We're gonna ask the result to be put into here
     458           0 :                         static ResultQueue<std::string, ClientCached*, u8, u8> result_queue;
     459             : 
     460             :                         // Throw a request in
     461           0 :                         m_get_clientcached_queue.add(name, 0, 0, &result_queue);
     462             :                         try{
     463           0 :                                 while(true) {
     464             :                                         // Wait result for a second
     465             :                                         GetResult<std::string, ClientCached*, u8, u8>
     466           0 :                                                 result = result_queue.pop_front(1000);
     467             : 
     468           0 :                                         if (result.key == name) {
     469           0 :                                                 return result.item;
     470             :                                         }
     471             :                                 }
     472             :                         }
     473           0 :                         catch(ItemNotFoundException &e)
     474             :                         {
     475           0 :                                 errorstream<<"Waiting for clientcached " << name << " timed out."<<std::endl;
     476           0 :                                 return &m_dummy_clientcached;
     477             :                         }
     478             :                 }
     479             :         }
     480             :         // Get item inventory texture
     481        8162 :         virtual video::ITexture* getInventoryTexture(const std::string &name,
     482             :                         IGameDef *gamedef) const
     483             :         {
     484        8162 :                 ClientCached *cc = getClientCached(name, gamedef);
     485        8162 :                 if(!cc)
     486           0 :                         return NULL;
     487        8162 :                 return cc->inventory_texture;
     488             :         }
     489             :         // Get item wield mesh
     490           0 :         virtual scene::IMesh* getWieldMesh(const std::string &name,
     491             :                         IGameDef *gamedef) const
     492             :         {
     493           0 :                 ClientCached *cc = getClientCached(name, gamedef);
     494           0 :                 if(!cc)
     495           0 :                         return NULL;
     496           0 :                 return cc->wield_mesh;
     497             :         }
     498             : #endif
     499           2 :         void clear()
     500             :         {
     501          16 :                 for(std::map<std::string, ItemDefinition*>::const_iterator
     502           2 :                                 i = m_item_definitions.begin();
     503          12 :                                 i != m_item_definitions.end(); i++)
     504             :                 {
     505           4 :                         delete i->second;
     506             :                 }
     507           2 :                 m_item_definitions.clear();
     508           2 :                 m_aliases.clear();
     509             : 
     510             :                 // Add the four builtin items:
     511             :                 //   "" is the hand
     512             :                 //   "unknown" is returned whenever an undefined item
     513             :                 //     is accessed (is also the unknown node)
     514             :                 //   "air" is the air node
     515             :                 //   "ignore" is the ignore node
     516             : 
     517           2 :                 ItemDefinition* hand_def = new ItemDefinition;
     518           2 :                 hand_def->name = "";
     519           2 :                 hand_def->wield_image = "wieldhand.png";
     520           2 :                 hand_def->tool_capabilities = new ToolCapabilities;
     521           2 :                 m_item_definitions.insert(std::make_pair("", hand_def));
     522             : 
     523           2 :                 ItemDefinition* unknown_def = new ItemDefinition;
     524           2 :                 unknown_def->type = ITEM_NODE;
     525           2 :                 unknown_def->name = "unknown";
     526           2 :                 m_item_definitions.insert(std::make_pair("unknown", unknown_def));
     527             : 
     528           2 :                 ItemDefinition* air_def = new ItemDefinition;
     529           2 :                 air_def->type = ITEM_NODE;
     530           2 :                 air_def->name = "air";
     531           2 :                 m_item_definitions.insert(std::make_pair("air", air_def));
     532             : 
     533           2 :                 ItemDefinition* ignore_def = new ItemDefinition;
     534           2 :                 ignore_def->type = ITEM_NODE;
     535           2 :                 ignore_def->name = "ignore";
     536           2 :                 m_item_definitions.insert(std::make_pair("ignore", ignore_def));
     537           2 :         }
     538        5500 :         virtual void registerItem(const ItemDefinition &def)
     539             :         {
     540        5500 :                 verbosestream<<"ItemDefManager: registering \""<<def.name<<"\""<<std::endl;
     541             :                 // Ensure that the "" item (the hand) always has ToolCapabilities
     542        5500 :                 if(def.name == "")
     543           1 :                         FATAL_ERROR_IF(!def.tool_capabilities, "Hand does not have ToolCapabilities");
     544             : 
     545        5500 :                 if(m_item_definitions.count(def.name) == 0)
     546        5496 :                         m_item_definitions[def.name] = new ItemDefinition(def);
     547             :                 else
     548           4 :                         *(m_item_definitions[def.name]) = def;
     549             : 
     550             :                 // Remove conflicting alias if it exists
     551        5500 :                 bool alias_removed = (m_aliases.erase(def.name) != 0);
     552        5500 :                 if(alias_removed)
     553           0 :                         infostream<<"ItemDefManager: erased alias "<<def.name
     554           0 :                                         <<" because item was defined"<<std::endl;
     555        5500 :         }
     556        1841 :         virtual void registerAlias(const std::string &name,
     557             :                         const std::string &convert_to)
     558             :         {
     559        1841 :                 if(m_item_definitions.find(name) == m_item_definitions.end())
     560             :                 {
     561        1841 :                         verbosestream<<"ItemDefManager: setting alias "<<name
     562        1841 :                                 <<" -> "<<convert_to<<std::endl;
     563        1841 :                         m_aliases[name] = convert_to;
     564             :                 }
     565        1841 :         }
     566           0 :         void serialize(std::ostream &os, u16 protocol_version)
     567             :         {
     568           0 :                 writeU8(os, 0); // version
     569           0 :                 u16 count = m_item_definitions.size();
     570           0 :                 writeU16(os, count);
     571             : 
     572           0 :                 for (std::map<std::string, ItemDefinition *>::const_iterator
     573           0 :                                 it = m_item_definitions.begin();
     574           0 :                                 it != m_item_definitions.end(); ++it) {
     575           0 :                         ItemDefinition *def = it->second;
     576             :                         // Serialize ItemDefinition and write wrapped in a string
     577           0 :                         std::ostringstream tmp_os(std::ios::binary);
     578           0 :                         def->serialize(tmp_os, protocol_version);
     579           0 :                         os << serializeString(tmp_os.str());
     580             :                 }
     581             : 
     582           0 :                 writeU16(os, m_aliases.size());
     583             : 
     584           0 :                 for (StringMap::const_iterator
     585           0 :                                 it = m_aliases.begin();
     586           0 :                                 it != m_aliases.end(); ++it) {
     587           0 :                         os << serializeString(it->first);
     588           0 :                         os << serializeString(it->second);
     589             :                 }
     590           0 :         }
     591           1 :         void deSerialize(std::istream &is)
     592             :         {
     593             :                 // Clear everything
     594           1 :                 clear();
     595             :                 // Deserialize
     596           1 :                 int version = readU8(is);
     597           1 :                 if(version != 0)
     598           0 :                         throw SerializationError("unsupported ItemDefManager version");
     599           1 :                 u16 count = readU16(is);
     600        5501 :                 for(u16 i=0; i<count; i++)
     601             :                 {
     602             :                         // Deserialize a string and grab an ItemDefinition from it
     603       11000 :                         std::istringstream tmp_is(deSerializeString(is), std::ios::binary);
     604       11000 :                         ItemDefinition def;
     605        5500 :                         def.deSerialize(tmp_is);
     606             :                         // Register
     607        5500 :                         registerItem(def);
     608             :                 }
     609           1 :                 u16 num_aliases = readU16(is);
     610        1842 :                 for(u16 i=0; i<num_aliases; i++)
     611             :                 {
     612        3682 :                         std::string name = deSerializeString(is);
     613        3682 :                         std::string convert_to = deSerializeString(is);
     614        1841 :                         registerAlias(name, convert_to);
     615             :                 }
     616           1 :         }
     617        1166 :         void processQueue(IGameDef *gamedef)
     618             :         {
     619             : #ifndef SERVER
     620             :                 //NOTE this is only thread safe for ONE consumer thread!
     621        1166 :                 while(!m_get_clientcached_queue.empty())
     622             :                 {
     623             :                         GetRequest<std::string, ClientCached*, u8, u8>
     624           0 :                                         request = m_get_clientcached_queue.pop();
     625             : 
     626           0 :                         m_get_clientcached_queue.pushResult(request,
     627           0 :                                         createClientCachedDirect(request.key, gamedef));
     628             :                 }
     629             : #endif
     630        1166 :         }
     631             : private:
     632             :         // Key is name
     633             :         std::map<std::string, ItemDefinition*> m_item_definitions;
     634             :         // Aliases
     635             :         StringMap m_aliases;
     636             : #ifndef SERVER
     637             :         // The id of the thread that is allowed to use irrlicht directly
     638             :         threadid_t m_main_thread;
     639             :         // A reference to this can be returned when nothing is found, to avoid NULLs
     640             :         mutable ClientCached m_dummy_clientcached;
     641             :         // Cached textures and meshes
     642             :         mutable MutexedMap<std::string, ClientCached*> m_clientcached;
     643             :         // Queued clientcached fetches (to be processed by the main thread)
     644             :         mutable RequestQueue<std::string, ClientCached*, u8, u8> m_get_clientcached_queue;
     645             : #endif
     646             : };
     647             : 
     648           1 : IWritableItemDefManager* createItemDefManager()
     649             : {
     650           1 :         return new CItemDefManager();
     651           3 : }

Generated by: LCOV version 1.11