X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fnodedef.cpp;h=2b6de0461b14e505918d050b66152722b84bf1ee;hb=eda9214f81b32d9606f425e3777616e8cfc0a44f;hp=59db68a3629ec1e416c019bf1583d524797e547f;hpb=414f0275cfa014423394cc9c37ecb0151c3bd46c;p=dragonfireclient.git diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 59db68a36..2b6de0461 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "settings.h" #include "nameidmapping.h" +#include "util/numeric.h" #include "util/serialize.h" //#include "profiler.h" // For TimeTaker @@ -45,12 +46,17 @@ void NodeBox::reset() wall_side = aabb3f(-BS/2, -BS/2, -BS/2, -BS/2+BS/16., BS/2, BS/2); } -void NodeBox::serialize(std::ostream &os) const +void NodeBox::serialize(std::ostream &os, u16 protocol_version) const { - writeU8(os, 1); // version - writeU8(os, type); + int version = protocol_version >= 21 ? 2 : 1; + writeU8(os, version); - if(type == NODEBOX_FIXED) + if (version == 1 && type == NODEBOX_LEVELED) + writeU8(os, NODEBOX_FIXED); + else + writeU8(os, type); + + if(type == NODEBOX_FIXED || type == NODEBOX_LEVELED) { writeU16(os, fixed.size()); for(std::vector::const_iterator @@ -75,14 +81,14 @@ void NodeBox::serialize(std::ostream &os) const void NodeBox::deSerialize(std::istream &is) { int version = readU8(is); - if(version != 1) + if(version < 1 || version > 2) throw SerializationError("unsupported NodeBox version"); reset(); type = (enum NodeBoxType)readU8(is); - if(type == NODEBOX_FIXED) + if(type == NODEBOX_FIXED || type == NODEBOX_LEVELED) { u16 fixed_count = readU16(is); while(fixed_count--) @@ -206,15 +212,20 @@ void ContentFeatures::reset() climbable = false; buildable_to = false; rightclickable = true; + leveled = 0; liquid_type = LIQUID_NONE; liquid_alternative_flowing = ""; liquid_alternative_source = ""; liquid_viscosity = 0; liquid_renewable = true; + freezemelt = ""; + liquid_range = LIQUID_LEVEL_MAX+1; + drowning = 0; light_source = 0; damage_per_second = 0; node_box = NodeBox(); selection_box = NodeBox(); + waving = 0; legacy_facedir_simple = false; legacy_wallmounted = false; sound_footstep = SimpleSoundSpec(); @@ -269,16 +280,20 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) writeU8(os, liquid_renewable); writeU8(os, light_source); writeU32(os, damage_per_second); - node_box.serialize(os); - selection_box.serialize(os); + node_box.serialize(os, protocol_version); + selection_box.serialize(os, protocol_version); writeU8(os, legacy_facedir_simple); writeU8(os, legacy_wallmounted); serializeSimpleSoundSpec(sound_footstep, os); serializeSimpleSoundSpec(sound_dig, os); serializeSimpleSoundSpec(sound_dug, os); writeU8(os, rightclickable); + writeU8(os, drowning); + writeU8(os, leveled); + writeU8(os, liquid_range); // Stuff below should be moved to correct place in a version that otherwise changes // the protocol version + writeU8(os, waving); } void ContentFeatures::deSerialize(std::istream &is) @@ -338,11 +353,15 @@ void ContentFeatures::deSerialize(std::istream &is) deSerializeSimpleSoundSpec(sound_dig, is); deSerializeSimpleSoundSpec(sound_dug, is); rightclickable = readU8(is); + drowning = readU8(is); + leveled = readU8(is); + liquid_range = 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 + waving = readU8(is); }catch(SerializationError &e) {}; } @@ -355,61 +374,66 @@ class CNodeDefManager: public IWritableNodeDefManager public: void 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); - for(u16 i=0; i<=MAX_CONTENT; i++) + // Set CONTENT_UNKNOWN { - ContentFeatures &f = m_content_features[i]; - f.reset(); // Reset to defaults + 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.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.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.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; - // A way to remove accidental CONTENT_IGNOREs - f.buildable_to = true; + 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); } } - // CONTENT_IGNORE = not found - content_t getFreeId() - { - for(u32 i=0; i<=0xffff; i++){ - const ContentFeatures &f = m_content_features[i]; - if(f.name == "") - return i; - } - return CONTENT_IGNORE; - } CNodeDefManager() { clear(); @@ -420,16 +444,15 @@ class CNodeDefManager: public IWritableNodeDefManager virtual IWritableNodeDefManager* clone() { CNodeDefManager *mgr = new CNodeDefManager(); - for(u16 i=0; i<=MAX_CONTENT; i++) - { - mgr->set(i, get(i)); - } + *mgr = *this; return mgr; } virtual const ContentFeatures& get(content_t c) const { - assert(c <= MAX_CONTENT); - return m_content_features[c]; + if(c < m_content_features.size()) + return m_content_features[c]; + else + return m_content_features[CONTENT_UNKNOWN]; } virtual const ContentFeatures& get(const MapNode &n) const { @@ -462,7 +485,6 @@ class CNodeDefManager: public IWritableNodeDefManager } std::string group = name.substr(6); -#if 1 // Optimized version, takes less than 1 microsecond at -O1 std::map::const_iterator i = m_group_to_items.find(group); if (i == m_group_to_items.end()) @@ -474,50 +496,67 @@ class CNodeDefManager: public IWritableNodeDefManager if ((*j).second != 0) result.insert((*j).first); } -#else // Old version, takes about ~150-200us at -O1 - for(u16 id=0; id<=MAX_CONTENT; id++) - { - const ContentFeatures &f = m_content_features[id]; - if(f.name == "") // Quickly discard undefined nodes - continue; - if(itemgroup_get(f.groups, group) != 0) - result.insert(id); - } -#endif //printf("getIds: %dus\n", t.stop()); } virtual const ContentFeatures& get(const std::string &name) const { - content_t id = CONTENT_IGNORE; + content_t id = CONTENT_UNKNOWN; getId(name, id); return get(id); } + // returns CONTENT_IGNORE if no free ID found + content_t allocateId() + { + for(content_t id = m_next_id; + id >= m_next_id; // overflow? + ++id){ + while(id >= m_content_features.size()){ + m_content_features.push_back(ContentFeatures()); + } + const ContentFeatures &f = m_content_features[id]; + if(f.name == ""){ + m_next_id = id + 1; + return id; + } + } + // If we arrive here, an overflow occurred in id. + // That means no ID was found + return CONTENT_IGNORE; + } // IWritableNodeDefManager - virtual void set(content_t c, const ContentFeatures &def) + virtual content_t set(const std::string &name, + const ContentFeatures &def) { - verbosestream<<"registerNode: registering content id \""<first; @@ -525,28 +564,13 @@ class CNodeDefManager: public IWritableNodeDefManager std::map::iterator j = m_group_to_items.find(group_name); if (j == m_group_to_items.end()) { - m_group_to_items[group_name].push_back(std::make_pair(c, i->second)); + m_group_to_items[group_name].push_back( + std::make_pair(id, i->second)); } else { GroupItems &items = j->second; - items.push_back(std::make_pair(c, i->second)); + items.push_back(std::make_pair(id, i->second)); } } - } - virtual content_t set(const std::string &name, - const ContentFeatures &def) - { - assert(name == def.name); - u16 id = CONTENT_IGNORE; - bool found = m_name_id_mapping.getId(name, id); // ignore aliases - if(!found){ - // Get some id - id = getFreeId(); - if(id == CONTENT_IGNORE) - return CONTENT_IGNORE; - if(name != "") - addNameIdMapping(id, name); - } - set(id, def); return id; } virtual content_t allocateDummy(const std::string &name) @@ -583,7 +607,7 @@ class CNodeDefManager: public IWritableNodeDefManager bool new_style_leaves = g_settings->getBool("new_style_leaves"); bool opaque_water = g_settings->getBool("opaque_water"); - for(u16 i=0; i<=MAX_CONTENT; i++) + for(u32 i=0; itiledef[j]; if(tiledef[j].name == "") - tiledef[j].name = "unknown_block.png"; + tiledef[j].name = "unknown_node.png"; } bool is_liquid = false; + u8 material_type; + material_type = (f->alpha == 255) ? TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA; + switch(f->drawtype){ default: case NDT_NORMAL: @@ -628,6 +655,10 @@ class CNodeDefManager: public IWritableNodeDefManager f->solidness = 0; f->visual_solidness = 1; break; + case NDT_GLASSLIKE_FRAMED: + f->solidness = 0; + f->visual_solidness = 1; + break; case NDT_ALLFACES: f->solidness = 0; f->visual_solidness = 1; @@ -644,10 +675,14 @@ class CNodeDefManager: public IWritableNodeDefManager tiledef[i].name += std::string("^[noalpha"); } } + if (f->waving == 1) + material_type = TILE_MATERIAL_LEAVES; break; case NDT_PLANTLIKE: f->solidness = 0; f->backface_culling = false; + if (f->waving == 1) + material_type = TILE_MATERIAL_PLANTS; break; case NDT_TORCHLIKE: case NDT_SIGNLIKE: @@ -658,20 +693,15 @@ class CNodeDefManager: public IWritableNodeDefManager break; } - u8 material_type = 0; - if(is_liquid){ - if(f->alpha == 255) - material_type = TILE_MATERIAL_LIQUID_OPAQUE; - else - material_type = TILE_MATERIAL_LIQUID_TRANSPARENT; - } else{ - material_type = TILE_MATERIAL_BASIC; - } + if (is_liquid) + material_type = (f->alpha == 255) ? TILE_MATERIAL_LIQUID_OPAQUE : TILE_MATERIAL_LIQUID_TRANSPARENT; // Tiles (fill in f->tiles[]) for(u16 j=0; j<6; j++){ // Texture - f->tiles[j].texture = tsrc->getTexture(tiledef[j].name); + f->tiles[j].texture = tsrc->getTexture( + tiledef[j].name, + &f->tiles[j].texture_id); // Alpha f->tiles[j].alpha = f->alpha; // Material type @@ -686,10 +716,9 @@ class CNodeDefManager: public IWritableNodeDefManager if(f->tiles[j].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) { - // Get raw texture size to determine frame count by + // Get texture size to determine frame count by // aspect ratio - video::ITexture *t = tsrc->getTextureRaw(tiledef[j].name); - v2u32 size = t->getOriginalSize(); + v2u32 size = f->tiles[j].texture->getOriginalSize(); int frame_height = (float)size.X / (float)tiledef[j].animation.aspect_w * (float)tiledef[j].animation.aspect_h; @@ -712,8 +741,9 @@ class CNodeDefManager: public IWritableNodeDefManager // Special tiles (fill in f->special_tiles[]) for(u16 j=0; jspecial_tiles[j].texture = - tsrc->getTexture(f->tiledef_special[j].name); + f->special_tiles[j].texture = tsrc->getTexture( + f->tiledef_special[j].name, + &f->special_tiles[j].texture_id); // Alpha f->special_tiles[j].alpha = f->alpha; // Material type @@ -728,10 +758,9 @@ class CNodeDefManager: public IWritableNodeDefManager if(f->special_tiles[j].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) { - // Get raw texture size to determine frame count by + // Get texture size to determine frame count by // aspect ratio - video::ITexture *t = tsrc->getTextureRaw(f->tiledef_special[j].name); - v2u32 size = t->getOriginalSize(); + v2u32 size = f->special_tiles[j].texture->getOriginalSize(); int frame_height = (float)size.X / (float)f->tiledef_special[j].animation.aspect_w * (float)f->tiledef_special[j].animation.aspect_h; @@ -759,9 +788,10 @@ class CNodeDefManager: public IWritableNodeDefManager writeU8(os, 1); // version u16 count = 0; std::ostringstream os2(std::ios::binary); - for(u16 i=0; i<=MAX_CONTENT; i++) + for(u32 i=0; iname == "") @@ -772,6 +802,8 @@ class CNodeDefManager: public IWritableNodeDefManager std::ostringstream wrapper_os(std::ios::binary); f->serialize(wrapper_os, protocol_version); os2< count); // must not overflow count++; } writeU16(os, count); @@ -785,24 +817,43 @@ class CNodeDefManager: public IWritableNodeDefManager throw SerializationError("unsupported NodeDefinitionManager version"); u16 count = readU16(is); std::istringstream is2(deSerializeLongString(is), std::ios::binary); + ContentFeatures f; for(u16 n=0; n MAX_CONTENT){ - errorstream<<"ContentFeatures::deSerialize(): " - <<"Too large content id: "<deSerialize(wrapper_is); - verbosestream<<"deserialized "<name<name != "") - addNameIdMapping(i, f->name); + f.deSerialize(wrapper_is); + + // Check error conditions + if(i == CONTENT_IGNORE || i == CONTENT_AIR + || i == CONTENT_UNKNOWN){ + infostream<<"NodeDefManager::deSerialize(): WARNING: " + <<"not changing builtin node "<= m_content_features.size()) + m_content_features.resize((u32)(i) + 1); + m_content_features[i] = f; + addNameIdMapping(i, f.name); + verbosestream<<"deserialized "< 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 @@ -822,7 +873,10 @@ class CNodeDefManager: public IWritableNodeDefManager std::map 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 m_group_to_items; + // Next possibly free id + content_t m_next_id; }; IWritableNodeDefManager* createNodeDefManager() @@ -877,8 +931,8 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) writeU8(os, liquid_viscosity); writeU8(os, light_source); writeU32(os, damage_per_second); - node_box.serialize(os); - selection_box.serialize(os); + node_box.serialize(os, protocol_version); + selection_box.serialize(os, protocol_version); writeU8(os, legacy_facedir_simple); writeU8(os, legacy_wallmounted); serializeSimpleSoundSpec(sound_footstep, os);