+ legacy_facedir_simple = readU8(is);
+ legacy_wallmounted = readU8(is);
+ deSerializeSimpleSoundSpec(sound_footstep, is);
+ deSerializeSimpleSoundSpec(sound_dig, is);
+ deSerializeSimpleSoundSpec(sound_dug, is);
+ rightclickable = readU8(is);
+ drowning = readU8(is);
+ leveled = readU8(is);
+ liquid_range = readU8(is);
+ waving = readU8(is);
+ // If you add anything here, insert it primarily inside the try-catch
+ // block to not need to increase the version.
+ try{
+ // Stuff below should be moved to correct place in a version that
+ // otherwise changes the protocol version
+ mesh = deSerializeString(is);
+ collision_box.deSerialize(is);
+ }catch(SerializationError &e) {};
+}
+
+/*
+ CNodeDefManager
+*/
+
+class CNodeDefManager: public IWritableNodeDefManager {
+public:
+ CNodeDefManager();
+ virtual ~CNodeDefManager();
+ void clear();
+ virtual IWritableNodeDefManager *clone();
+ virtual const ContentFeatures& get(content_t c) const;
+ virtual const ContentFeatures& get(const MapNode &n) const;
+ virtual bool getId(const std::string &name, content_t &result) const;
+ virtual content_t getId(const std::string &name) const;
+ virtual void getIds(const std::string &name, std::set<content_t> &result) const;
+ virtual const ContentFeatures& get(const std::string &name) const;
+ content_t allocateId();
+ virtual content_t set(const std::string &name, const ContentFeatures &def);
+ virtual content_t allocateDummy(const std::string &name);
+ virtual void updateAliases(IItemDefManager *idef);
+ virtual void updateTextures(IGameDef *gamedef);
+ void serialize(std::ostream &os, u16 protocol_version);
+ void deSerialize(std::istream &is);
+ virtual NodeResolver *getResolver();
+
+private:
+ void addNameIdMapping(content_t i, std::string name);
+#ifndef SERVER
+ void fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, TileDef *tiledef,
+ u32 shader_id, bool use_normal_texture, bool backface_culling,
+ u8 alpha, u8 material_type);
+#endif
+
+ // Features indexed by id
+ std::vector<ContentFeatures> m_content_features;
+
+ // A mapping for fast converting back and forth between names and ids
+ NameIdMapping m_name_id_mapping;
+
+ // Like m_name_id_mapping, but only from names to ids, and includes
+ // item aliases too. Updated by updateAliases()
+ // Note: Not serialized.
+
+ std::map<std::string, content_t> m_name_id_mapping_with_aliases;
+
+ // A mapping from groups to a list of content_ts (and their levels)
+ // that belong to it. Necessary for a direct lookup in getIds().
+ // Note: Not serialized.
+ std::map<std::string, GroupItems> m_group_to_items;
+
+ // Next possibly free id
+ content_t m_next_id;
+
+ // NodeResolver to queue pending node resolutions
+ NodeResolver m_resolver;
+};
+
+
+CNodeDefManager::CNodeDefManager() :
+ m_resolver(this)
+{
+ clear();
+}
+
+
+CNodeDefManager::~CNodeDefManager()
+{
+#ifndef SERVER
+ for (u32 i = 0; i < m_content_features.size(); i++) {
+ ContentFeatures *f = &m_content_features[i];
+ for (u32 j = 0; j < 24; j++) {
+ if (f->mesh_ptr[j])
+ f->mesh_ptr[j]->drop();
+ }
+ }
+#endif
+}
+
+
+void CNodeDefManager::clear()
+{
+ m_content_features.clear();
+ m_name_id_mapping.clear();
+ m_name_id_mapping_with_aliases.clear();
+ m_group_to_items.clear();
+ m_next_id = 0;
+
+ u32 initial_length = 0;
+ initial_length = MYMAX(initial_length, CONTENT_UNKNOWN + 1);
+ initial_length = MYMAX(initial_length, CONTENT_AIR + 1);
+ initial_length = MYMAX(initial_length, CONTENT_IGNORE + 1);
+ m_content_features.resize(initial_length);
+
+ // Set CONTENT_UNKNOWN
+ {
+ ContentFeatures f;
+ f.name = "unknown";
+ // Insert directly into containers
+ content_t c = CONTENT_UNKNOWN;
+ m_content_features[c] = f;
+ addNameIdMapping(c, f.name);
+ }
+
+ // Set CONTENT_AIR
+ {
+ ContentFeatures f;
+ f.name = "air";
+ f.drawtype = NDT_AIRLIKE;
+ f.param_type = CPT_LIGHT;
+ f.light_propagates = true;
+ f.sunlight_propagates = true;
+ f.walkable = false;
+ f.pointable = false;
+ f.diggable = false;
+ f.buildable_to = true;
+ f.is_ground_content = true;
+ // Insert directly into containers
+ content_t c = CONTENT_AIR;
+ m_content_features[c] = f;
+ addNameIdMapping(c, f.name);
+ }
+
+ // Set CONTENT_IGNORE
+ {
+ ContentFeatures f;
+ f.name = "ignore";
+ f.drawtype = NDT_AIRLIKE;
+ f.param_type = CPT_NONE;
+ f.light_propagates = false;
+ f.sunlight_propagates = false;
+ f.walkable = false;
+ f.pointable = false;
+ f.diggable = false;
+ f.buildable_to = true; // A way to remove accidental CONTENT_IGNOREs
+ f.is_ground_content = true;
+ // Insert directly into containers
+ content_t c = CONTENT_IGNORE;
+ m_content_features[c] = f;
+ addNameIdMapping(c, f.name);
+ }
+}
+
+
+IWritableNodeDefManager *CNodeDefManager::clone()
+{
+ CNodeDefManager *mgr = new CNodeDefManager();
+ *mgr = *this;
+ return mgr;