X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fnodedef.cpp;h=5a1578bba589f416fd0f26770b648df6f501a82f;hb=9c635f28ac2b103bf7196e47947bf64673c13393;hp=f87daa528adfd7e394e378d7cd2da67380c6c6cb;hpb=08d259cf41db805ada7c39a39ffe9dcec4f0c230;p=minetest.git diff --git a/src/nodedef.cpp b/src/nodedef.cpp index f87daa528..5a1578bba 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -19,10 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" -#include "main.h" // For g_settings #include "itemdef.h" #ifndef SERVER -#include "tile.h" +#include "client/tile.h" #include "mesh.h" #include #endif @@ -34,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "exceptions.h" #include "debug.h" #include "gamedef.h" +#include // Used in applyTextureOverrides() /* NodeBox @@ -65,7 +65,7 @@ void NodeBox::serialize(std::ostream &os, u16 protocol_version) const writeU16(os, fixed.size()); for(std::vector::const_iterator i = fixed.begin(); - i != fixed.end(); i++) + i != fixed.end(); ++i) { writeV3F1000(os, i->MinEdge); writeV3F1000(os, i->MaxEdge); @@ -120,7 +120,9 @@ void NodeBox::deSerialize(std::istream &is) void TileDef::serialize(std::ostream &os, u16 protocol_version) const { - if(protocol_version >= 17) + if (protocol_version >= 26) + writeU8(os, 2); + else if (protocol_version >= 17) writeU8(os, 1); else writeU8(os, 0); @@ -129,8 +131,12 @@ void TileDef::serialize(std::ostream &os, u16 protocol_version) const writeU16(os, animation.aspect_w); writeU16(os, animation.aspect_h); writeF1000(os, animation.length); - if(protocol_version >= 17) + if (protocol_version >= 17) writeU8(os, backface_culling); + if (protocol_version >= 26) { + writeU8(os, tileable_horizontal); + writeU8(os, tileable_vertical); + } } void TileDef::deSerialize(std::istream &is) @@ -141,10 +147,15 @@ void TileDef::deSerialize(std::istream &is) animation.aspect_w = readU16(is); animation.aspect_h = readU16(is); animation.length = readF1000(is); - if(version >= 1) + if (version >= 1) backface_culling = readU8(is); + if (version >= 2) { + tileable_horizontal = readU8(is); + tileable_vertical = readU8(is); + } } + /* SimpleSoundSpec serialization */ @@ -183,6 +194,7 @@ void ContentFeatures::reset() solidness = 2; visual_solidness = 0; backface_culling = true; + #endif has_on_construct = false; has_on_destruct = false; @@ -202,6 +214,7 @@ void ContentFeatures::reset() #ifndef SERVER for(u32 i = 0; i < 24; i++) mesh_ptr[i] = NULL; + minimap_color = video::SColor(0, 0, 0, 0); #endif visual_scale = 1.0; for(u32 i = 0; i < 6; i++) @@ -227,7 +240,6 @@ void ContentFeatures::reset() liquid_alternative_source = ""; liquid_viscosity = 0; liquid_renewable = true; - freezemelt = ""; liquid_range = LIQUID_LEVEL_MAX+1; drowning = 0; light_source = 0; @@ -243,7 +255,7 @@ void ContentFeatures::reset() sound_dug = SimpleSoundSpec(); } -void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) +void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const { if(protocol_version < 24){ serializeOld(os, protocol_version); @@ -254,7 +266,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) os<first); writeS16(os, i->second); } @@ -399,18 +411,20 @@ class CNodeDefManager: public IWritableNodeDefManager { 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); + virtual void applyTextureOverrides(const std::string &override_filepath); + virtual void updateTextures(IGameDef *gamedef, + void (*progress_cbk)(void *progress_args, u32 progress, u32 max_progress), + void *progress_cbk_args); + void serialize(std::ostream &os, u16 protocol_version) const; void deSerialize(std::istream &is); - virtual void pendNodeResolve(NodeResolveInfo *nri); - virtual void cancelNodeResolve(NodeResolver *resolver); - virtual void runNodeResolverCallbacks(); + inline virtual bool getNodeRegistrationStatus() const; + inline virtual void setNodeRegistrationStatus(bool completed); - virtual bool getIdFromResolveInfo(NodeResolveInfo *nri, - const std::string &node_alt, content_t c_fallback, content_t &result); - virtual bool getIdsFromResolveInfo(NodeResolveInfo *nri, - std::vector &result); + virtual void pendNodeResolve(NodeResolver *nr); + virtual bool cancelNodeResolveCallback(NodeResolver *nr); + virtual void runNodeResolveCallbacks(); + virtual void resetNodeResolveState(); private: void addNameIdMapping(content_t i, std::string name); @@ -440,8 +454,11 @@ class CNodeDefManager: public IWritableNodeDefManager { // Next possibly free id content_t m_next_id; - // List of node strings and node resolver callbacks to perform - std::list m_pending_node_lookups; + // NodeResolvers to callback once node registration has ended + std::vector m_pending_resolve_callbacks; + + // True when all nodes have been registered + bool m_node_registration_complete; }; @@ -473,6 +490,8 @@ void CNodeDefManager::clear() m_group_to_items.clear(); m_next_id = 0; + resetNodeResolveState(); + u32 initial_length = 0; initial_length = MYMAX(initial_length, CONTENT_UNKNOWN + 1); initial_length = MYMAX(initial_length, CONTENT_AIR + 1); @@ -628,6 +647,7 @@ content_t CNodeDefManager::allocateId() // IWritableNodeDefManager content_t CNodeDefManager::set(const std::string &name, const ContentFeatures &def) { + // Pre-conditions assert(name != ""); assert(name == def.name); @@ -665,7 +685,7 @@ content_t CNodeDefManager::set(const std::string &name, const ContentFeatures &d 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(id, i->second)); + std::make_pair(id, i->second)); } else { GroupItems &items = j->second; items.push_back(std::make_pair(id, i->second)); @@ -677,7 +697,7 @@ content_t CNodeDefManager::set(const std::string &name, const ContentFeatures &d content_t CNodeDefManager::allocateDummy(const std::string &name) { - assert(name != ""); + assert(name != ""); // Pre-condition ContentFeatures f; f.name = name; return set(name, f); @@ -689,44 +709,110 @@ void CNodeDefManager::updateAliases(IItemDefManager *idef) std::set all = idef->getAll(); m_name_id_mapping_with_aliases.clear(); for (std::set::iterator - i = all.begin(); i != all.end(); i++) { + i = all.begin(); i != all.end(); ++i) { std::string name = *i; std::string convert_to = idef->getAlias(name); content_t id; if (m_name_id_mapping.getId(convert_to, id)) { m_name_id_mapping_with_aliases.insert( - std::make_pair(name, id)); + std::make_pair(name, id)); } } } +void CNodeDefManager::applyTextureOverrides(const std::string &override_filepath) +{ + infostream << "CNodeDefManager::applyTextureOverrides(): Applying " + "overrides to textures from " << override_filepath << std::endl; + + std::ifstream infile(override_filepath.c_str()); + std::string line; + int line_c = 0; + while (std::getline(infile, line)) { + line_c++; + if (trim(line) == "") + continue; + std::vector splitted = str_split(line, ' '); + if (splitted.size() != 3) { + errorstream << override_filepath + << ":" << line_c << " Could not apply texture override \"" + << line << "\": Syntax error" << std::endl; + continue; + } + + content_t id; + if (!getId(splitted[0], id)) { + errorstream << override_filepath + << ":" << line_c << " Could not apply texture override \"" + << line << "\": Unknown node \"" + << splitted[0] << "\"" << std::endl; + continue; + } -void CNodeDefManager::updateTextures(IGameDef *gamedef) + ContentFeatures &nodedef = m_content_features[id]; + + if (splitted[1] == "top") + nodedef.tiledef[0].name = splitted[2]; + else if (splitted[1] == "bottom") + nodedef.tiledef[1].name = splitted[2]; + else if (splitted[1] == "right") + nodedef.tiledef[2].name = splitted[2]; + else if (splitted[1] == "left") + nodedef.tiledef[3].name = splitted[2]; + else if (splitted[1] == "back") + nodedef.tiledef[4].name = splitted[2]; + else if (splitted[1] == "front") + nodedef.tiledef[5].name = splitted[2]; + else if (splitted[1] == "all" || splitted[1] == "*") + for (int i = 0; i < 6; i++) + nodedef.tiledef[i].name = splitted[2]; + else if (splitted[1] == "sides") + for (int i = 2; i < 6; i++) + nodedef.tiledef[i].name = splitted[2]; + else { + errorstream << override_filepath + << ":" << line_c << " Could not apply texture override \"" + << line << "\": Unknown node side \"" + << splitted[1] << "\"" << std::endl; + continue; + } + } +} + +void CNodeDefManager::updateTextures(IGameDef *gamedef, + void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress), + void *progress_callback_args) { #ifndef SERVER infostream << "CNodeDefManager::updateTextures(): Updating " "textures in node definitions" << std::endl; - ITextureSource *tsrc = gamedef->tsrc(); IShaderSource *shdsrc = gamedef->getShaderSource(); scene::ISceneManager* smgr = gamedef->getSceneManager(); scene::IMeshManipulator* meshmanip = smgr->getMeshManipulator(); bool new_style_water = g_settings->getBool("new_style_water"); - bool new_style_leaves = g_settings->getBool("new_style_leaves"); bool connected_glass = g_settings->getBool("connected_glass"); bool opaque_water = g_settings->getBool("opaque_water"); bool enable_shaders = g_settings->getBool("enable_shaders"); bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping"); bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion"); bool enable_mesh_cache = g_settings->getBool("enable_mesh_cache"); + bool enable_minimap = g_settings->getBool("enable_minimap"); + std::string leaves_style = g_settings->get("leaves_style"); bool use_normal_texture = enable_shaders && (enable_bumpmapping || enable_parallax_occlusion); - for (u32 i = 0; i < m_content_features.size(); i++) { + u32 size = m_content_features.size(); + + for (u32 i = 0; i < size; i++) { ContentFeatures *f = &m_content_features[i]; + // minimap pixel color - the average color of a texture + if (enable_minimap && f->tiledef[0].name != "") + f->minimap_color = tsrc->getTextureAverageColor(f->tiledef[0].name); + // Figure out the actual tiles to use TileDef tiledef[6]; for (u32 j = 0; j < 6; j++) { @@ -786,10 +872,18 @@ void CNodeDefManager::updateTextures(IGameDef *gamedef) f->visual_solidness = 1; break; case NDT_ALLFACES_OPTIONAL: - if (new_style_leaves) { + if (leaves_style == "fancy") { f->drawtype = NDT_ALLFACES; f->solidness = 0; f->visual_solidness = 1; + } else if (leaves_style == "simple") { + for (u32 j = 0; j < 6; j++) { + if (f->tiledef_special[j].name != "") + tiledef[j].name = f->tiledef_special[j].name; + } + f->drawtype = NDT_GLASSLIKE; + f->solidness = 0; + f->visual_solidness = 1; } else { f->drawtype = NDT_NORMAL; f->solidness = 2; @@ -897,6 +991,8 @@ void CNodeDefManager::updateTextures(IGameDef *gamedef) recalculateBoundingBox(f->mesh_ptr[0]); meshmanip->recalculateNormals(f->mesh_ptr[0], true, false); } + + progress_callback(progress_callback_args, i, size); } #endif } @@ -908,13 +1004,15 @@ void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, bool backface_culling, u8 alpha, u8 material_type) { tile->shader_id = shader_id; - tile->texture = tsrc->getTexture(tiledef->name, &tile->texture_id); + tile->texture = tsrc->getTextureForMesh(tiledef->name, &tile->texture_id); tile->alpha = alpha; tile->material_type = material_type; - // Normal texture - if (use_normal_texture) + // Normal texture and shader flags texture + if (use_normal_texture) { tile->normal_texture = tsrc->getNormalTexture(tiledef->name); + } + tile->flags_texture = tsrc->getShaderFlagsTexture(tile->normal_texture ? true : false); // Material flags tile->material_flags = 0; @@ -922,6 +1020,10 @@ void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, tile->material_flags |= MATERIAL_FLAG_BACKFACE_CULLING; if (tiledef->animation.type == TAT_VERTICAL_FRAMES) tile->material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; + if (tiledef->tileable_horizontal) + tile->material_flags |= MATERIAL_FLAG_TILEABLE_HORIZONTAL; + if (tiledef->tileable_vertical) + tile->material_flags |= MATERIAL_FLAG_TILEABLE_VERTICAL; // Animation parameters int frame_count = 1; @@ -951,9 +1053,10 @@ void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, os << tiledef->name << "^[verticalframe:" << frame_count << ":" << i; - frame.texture = tsrc->getTexture(os.str(), &frame.texture_id); + frame.texture = tsrc->getTextureForMesh(os.str(), &frame.texture_id); if (tile->normal_texture) frame.normal_texture = tsrc->getNormalTexture(os.str()); + frame.flags_texture = tile->flags_texture; tile->frames[i] = frame; } } @@ -961,7 +1064,7 @@ void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, #endif -void CNodeDefManager::serialize(std::ostream &os, u16 protocol_version) +void CNodeDefManager::serialize(std::ostream &os, u16 protocol_version) const { writeU8(os, 1); // version u16 count = 0; @@ -970,7 +1073,7 @@ void CNodeDefManager::serialize(std::ostream &os, u16 protocol_version) if (i == CONTENT_IGNORE || i == CONTENT_AIR || i == CONTENT_UNKNOWN) continue; - ContentFeatures *f = &m_content_features[i]; + const ContentFeatures *f = &m_content_features[i]; if (f->name == "") continue; writeU16(os2, i); @@ -980,7 +1083,9 @@ void CNodeDefManager::serialize(std::ostream &os, u16 protocol_version) f->serialize(wrapper_os, protocol_version); os2< count); // must not overflow + // must not overflow + u16 next = count + 1; + FATAL_ERROR_IF(next < count, "Overflow"); count++; } writeU16(os, count); @@ -1049,7 +1154,7 @@ IWritableNodeDefManager *createNodeDefManager() //// Serialization of old ContentFeatures formats -void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) +void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const { if (protocol_version == 13) { @@ -1057,7 +1162,7 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) os<first); writeS16(os, i->second); } @@ -1105,7 +1210,7 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) os<first); writeS16(os, i->second); } @@ -1269,100 +1374,164 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version) } -void CNodeDefManager::pendNodeResolve(NodeResolveInfo *nri) +inline bool CNodeDefManager::getNodeRegistrationStatus() const { - nri->resolver->m_ndef = this; - m_pending_node_lookups.push_back(nri); + return m_node_registration_complete; } -void CNodeDefManager::cancelNodeResolve(NodeResolver *resolver) +inline void CNodeDefManager::setNodeRegistrationStatus(bool completed) { - for (std::list::iterator - it = m_pending_node_lookups.begin(); - it != m_pending_node_lookups.end(); - ++it) { - NodeResolveInfo *nri = *it; - if (resolver == nri->resolver) { - it = m_pending_node_lookups.erase(it); - delete nri; - } + m_node_registration_complete = completed; +} + + +void CNodeDefManager::pendNodeResolve(NodeResolver *nr) +{ + nr->m_ndef = this; + if (m_node_registration_complete) + nr->nodeResolveInternal(); + else + m_pending_resolve_callbacks.push_back(nr); +} + + +bool CNodeDefManager::cancelNodeResolveCallback(NodeResolver *nr) +{ + size_t len = m_pending_resolve_callbacks.size(); + for (size_t i = 0; i != len; i++) { + if (nr != m_pending_resolve_callbacks[i]) + continue; + + len--; + m_pending_resolve_callbacks[i] = m_pending_resolve_callbacks[len]; + m_pending_resolve_callbacks.resize(len); + return true; } + + return false; } -void CNodeDefManager::runNodeResolverCallbacks() +void CNodeDefManager::runNodeResolveCallbacks() { - while (!m_pending_node_lookups.empty()) { - NodeResolveInfo *nri = m_pending_node_lookups.front(); - m_pending_node_lookups.pop_front(); - nri->resolver->resolveNodeNames(nri); - nri->resolver->m_lookup_done = true; - delete nri; + for (size_t i = 0; i != m_pending_resolve_callbacks.size(); i++) { + NodeResolver *nr = m_pending_resolve_callbacks[i]; + nr->nodeResolveInternal(); } + + m_pending_resolve_callbacks.clear(); +} + + +void CNodeDefManager::resetNodeResolveState() +{ + m_node_registration_complete = false; + m_pending_resolve_callbacks.clear(); } -bool CNodeDefManager::getIdFromResolveInfo(NodeResolveInfo *nri, - const std::string &node_alt, content_t c_fallback, content_t &result) +//// +//// NodeResolver +//// + +NodeResolver::NodeResolver() { - if (nri->nodenames.empty()) { - result = c_fallback; - errorstream << "Resolver empty nodename list" << std::endl; + m_ndef = NULL; + m_nodenames_idx = 0; + m_nnlistsizes_idx = 0; + m_resolve_done = false; + + m_nodenames.reserve(16); + m_nnlistsizes.reserve(4); +} + + +NodeResolver::~NodeResolver() +{ + if (!m_resolve_done && m_ndef) + m_ndef->cancelNodeResolveCallback(this); +} + + +void NodeResolver::nodeResolveInternal() +{ + m_nodenames_idx = 0; + m_nnlistsizes_idx = 0; + + resolveNodeNames(); + m_resolve_done = true; + + m_nodenames.clear(); + m_nnlistsizes.clear(); +} + + +bool NodeResolver::getIdFromNrBacklog(content_t *result_out, + const std::string &node_alt, content_t c_fallback) +{ + if (m_nodenames_idx == m_nodenames.size()) { + *result_out = c_fallback; + errorstream << "NodeResolver: no more nodes in list" << std::endl; return false; } content_t c; - std::string name = nri->nodenames.front(); - nri->nodenames.pop_front(); + std::string name = m_nodenames[m_nodenames_idx++]; - bool success = getId(name, c); + bool success = m_ndef->getId(name, c); if (!success && node_alt != "") { name = node_alt; - success = getId(name, c); + success = m_ndef->getId(name, c); } if (!success) { - errorstream << "Resolver: Failed to resolve node name '" << name + errorstream << "NodeResolver: failed to resolve node name '" << name << "'." << std::endl; c = c_fallback; } - result = c; + *result_out = c; return success; } -bool CNodeDefManager::getIdsFromResolveInfo(NodeResolveInfo *nri, - std::vector &result) +bool NodeResolver::getIdsFromNrBacklog(std::vector *result_out, + bool all_required, content_t c_fallback) { bool success = true; - if (nri->nodelistinfo.empty()) { - errorstream << "Resolver: Empty nodelistinfo list" << std::endl; + if (m_nnlistsizes_idx == m_nnlistsizes.size()) { + errorstream << "NodeResolver: no more node lists" << std::endl; return false; } - NodeListInfo listinfo = nri->nodelistinfo.front(); - nri->nodelistinfo.pop_front(); + size_t length = m_nnlistsizes[m_nnlistsizes_idx++]; - while (listinfo.length--) { - if (nri->nodenames.empty()) { - errorstream << "Resolver: Empty nodename list" << std::endl; + while (length--) { + if (m_nodenames_idx == m_nodenames.size()) { + errorstream << "NodeResolver: no more nodes in list" << std::endl; return false; } content_t c; - std::string name = nri->nodenames.front(); - nri->nodenames.pop_front(); - - if (getId(name, c)) { - result.push_back(c); - } else if (listinfo.all_required) { - errorstream << "Resolver: Failed to resolve node name '" << name - << "'." << std::endl; - result.push_back(listinfo.c_fallback); - success = false; + std::string &name = m_nodenames[m_nodenames_idx++]; + + if (name.substr(0,6) != "group:") { + if (m_ndef->getId(name, c)) { + result_out->push_back(c); + } else if (all_required) { + errorstream << "NodeResolver: failed to resolve node name '" + << name << "'." << std::endl; + result_out->push_back(c_fallback); + success = false; + } + } else { + std::set cids; + std::set::iterator it; + m_ndef->getIds(name, cids); + for (it = cids.begin(); it != cids.end(); ++it) + result_out->push_back(*it); } }