X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fnodedef.cpp;h=d644dc229d2c4af9f3fbf3edc073aba6f818aaee;hb=43ebec2be1949aa5eac127df7cb902d37e4e461b;hp=7855ffef7e3207a0fa716ea07bf5571cd93de3ed;hpb=1f53ca5f4c2736ab060d93885d9bd956f14ae430;p=minetest.git diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 7855ffef7..d644dc229 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -3,16 +3,16 @@ Minetest-c55 Copyright (C) 2010 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GNU Lesser General Public License for more details. -You should have received a copy of the GNU General Public License along +You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -20,62 +20,129 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" #include "main.h" // For g_settings -#include "nodemetadata.h" +#include "itemdef.h" #ifndef SERVER #include "tile.h" #endif #include "log.h" #include "settings.h" #include "nameidmapping.h" +#include "util/serialize.h" /* NodeBox */ +void NodeBox::reset() +{ + type = NODEBOX_REGULAR; + // default is empty + fixed.clear(); + // default is sign/ladder-like + wall_top = aabb3f(-BS/2, BS/2-BS/16., -BS/2, BS/2, BS/2, BS/2); + wall_bottom = aabb3f(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2); + wall_side = aabb3f(-BS/2, -BS/2, -BS/2, -BS/2+BS/16., BS/2, BS/2); +} + void NodeBox::serialize(std::ostream &os) const { - writeU8(os, 0); // version + writeU8(os, 1); // version writeU8(os, type); - writeV3F1000(os, fixed.MinEdge); - writeV3F1000(os, fixed.MaxEdge); - writeV3F1000(os, wall_top.MinEdge); - writeV3F1000(os, wall_top.MaxEdge); - writeV3F1000(os, wall_bottom.MinEdge); - writeV3F1000(os, wall_bottom.MaxEdge); - writeV3F1000(os, wall_side.MinEdge); - writeV3F1000(os, wall_side.MaxEdge); + + if(type == NODEBOX_FIXED) + { + writeU16(os, fixed.size()); + for(std::vector::const_iterator + i = fixed.begin(); + i != fixed.end(); i++) + { + writeV3F1000(os, i->MinEdge); + writeV3F1000(os, i->MaxEdge); + } + } + else if(type == NODEBOX_WALLMOUNTED) + { + writeV3F1000(os, wall_top.MinEdge); + writeV3F1000(os, wall_top.MaxEdge); + writeV3F1000(os, wall_bottom.MinEdge); + writeV3F1000(os, wall_bottom.MaxEdge); + writeV3F1000(os, wall_side.MinEdge); + writeV3F1000(os, wall_side.MaxEdge); + } } void NodeBox::deSerialize(std::istream &is) { int version = readU8(is); - if(version != 0) + if(version != 1) throw SerializationError("unsupported NodeBox version"); + + reset(); + type = (enum NodeBoxType)readU8(is); - fixed.MinEdge = readV3F1000(is); - fixed.MaxEdge = readV3F1000(is); - wall_top.MinEdge = readV3F1000(is); - wall_top.MaxEdge = readV3F1000(is); - wall_bottom.MinEdge = readV3F1000(is); - wall_bottom.MaxEdge = readV3F1000(is); - wall_side.MinEdge = readV3F1000(is); - wall_side.MaxEdge = readV3F1000(is); + + if(type == NODEBOX_FIXED) + { + u16 fixed_count = readU16(is); + while(fixed_count--) + { + aabb3f box; + box.MinEdge = readV3F1000(is); + box.MaxEdge = readV3F1000(is); + fixed.push_back(box); + } + } + else if(type == NODEBOX_WALLMOUNTED) + { + wall_top.MinEdge = readV3F1000(is); + wall_top.MaxEdge = readV3F1000(is); + wall_bottom.MinEdge = readV3F1000(is); + wall_bottom.MaxEdge = readV3F1000(is); + wall_side.MinEdge = readV3F1000(is); + wall_side.MaxEdge = readV3F1000(is); + } } /* - MaterialSpec + TileDef */ + +void TileDef::serialize(std::ostream &os) const +{ + writeU8(os, 0); // version + os<first); + writeS16(os, i->second); + } writeU8(os, drawtype); writeF1000(os, visual_scale); writeU8(os, 6); for(u32 i=0; i<6; i++) - os<::const_iterator + i = m_name_id_mapping_with_aliases.find(name); + if(i == m_name_id_mapping_with_aliases.end()) + return false; + result = i->second; + return true; } virtual content_t getId(const std::string &name) const { @@ -409,6 +426,25 @@ class CNodeDefManager: public IWritableNodeDefManager getId(name, id); return id; } + virtual void getIds(const std::string &name, std::set &result) + const + { + if(name.substr(0,6) != "group:"){ + content_t id = CONTENT_IGNORE; + if(getId(name, id)) + result.insert(id); + return; + } + std::string group = name.substr(6); + 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); + } + } virtual const ContentFeatures& get(const std::string &name) const { content_t id = CONTENT_IGNORE; @@ -418,7 +454,7 @@ class CNodeDefManager: public IWritableNodeDefManager // IWritableNodeDefManager virtual void set(content_t c, const ContentFeatures &def) { - infostream<<"registerNode: registering content id \""< all = idef->getAll(); + m_name_id_mapping_with_aliases.clear(); + for(std::set::iterator + 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)); + } + } + } virtual void updateTextures(ITextureSource *tsrc) { #ifndef SERVER @@ -488,6 +530,15 @@ class CNodeDefManager: public IWritableNodeDefManager for(u16 i=0; i<=MAX_CONTENT; i++) { ContentFeatures *f = &m_content_features[i]; + + // Figure out the actual tiles to use + TileDef tiledef[6]; + for(u32 j=0; j<6; j++) + { + tiledef[j] = f->tiledef[j]; + if(tiledef[j].name == "") + tiledef[j].name = "unknown_block.png"; + } switch(f->drawtype){ default: @@ -505,8 +556,7 @@ class CNodeDefManager: public IWritableNodeDefManager f->solidness = 0; } else { f->solidness = 1; - if(f->alpha == 255) - f->solidness = 2; + f->backface_culling = false; } break; case NDT_FLOWINGLIQUID: @@ -530,10 +580,9 @@ class CNodeDefManager: public IWritableNodeDefManager f->visual_solidness = 1; } else { f->drawtype = NDT_NORMAL; - f->solidness = 1; + f->solidness = 2; for(u32 i=0; i<6; i++){ - f->tname_tiles[i] = f->tname_tiles[i] - + std::string("^[noalpha"); + tiledef[i].name += std::string("^[noalpha"); } } break; @@ -542,65 +591,106 @@ class CNodeDefManager: public IWritableNodeDefManager case NDT_PLANTLIKE: case NDT_FENCELIKE: case NDT_RAILLIKE: + case NDT_NODEBOX: f->solidness = 0; break; } - // Inventory texture - if(f->tname_inventory != "") - f->inventory_texture = tsrc->getTextureRaw(f->tname_inventory); - else - f->inventory_texture = NULL; - // Tile textures + // Tiles (fill in f->tiles[]) for(u16 j=0; j<6; j++){ - if(f->tname_tiles[j] == "") - continue; - f->tiles[j].texture = tsrc->getTexture(f->tname_tiles[j]); + // Texture + f->tiles[j].texture = tsrc->getTexture(tiledef[j].name); + // Alpha f->tiles[j].alpha = f->alpha; if(f->alpha == 255) f->tiles[j].material_type = MATERIAL_ALPHA_SIMPLE; else f->tiles[j].material_type = MATERIAL_ALPHA_VERTEX; + // Material flags + f->tiles[j].material_flags = 0; if(f->backface_culling) f->tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING; - else - f->tiles[j].material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING; + if(tiledef[j].animation.type == TAT_VERTICAL_FRAMES) + f->tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; + // Animation parameters + if(f->tiles[j].material_flags & + MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) + { + // Get raw texture size to determine frame count by + // aspect ratio + video::ITexture *t = tsrc->getTextureRaw(tiledef[j].name); + v2u32 size = t->getOriginalSize(); + int frame_height = (float)size.X / + (float)tiledef[j].animation.aspect_w * + (float)tiledef[j].animation.aspect_h; + int frame_count = size.Y / frame_height; + int frame_length_ms = 1000.0 * + tiledef[j].animation.length / frame_count; + f->tiles[j].animation_frame_count = frame_count; + f->tiles[j].animation_frame_length_ms = frame_length_ms; + + // If there are no frames for an animation, switch + // animation off (so that having specified an animation + // for something but not using it in the texture pack + // gives no overhead) + if(frame_count == 1){ + f->tiles[j].material_flags &= + ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; + } + } } - // Special textures + // Special tiles (fill in f->special_tiles[]) for(u16 j=0; jspecial_aps[j]){ - delete f->special_aps[j]; - f->special_aps[j] = NULL; - } - if(f->special_materials[j]){ - delete f->special_materials[j]; - f->special_materials[j] = NULL; + // Texture + f->special_tiles[j].texture = + tsrc->getTexture(f->tiledef_special[j].name); + // Alpha + f->special_tiles[j].alpha = f->alpha; + if(f->alpha == 255) + f->special_tiles[j].material_type = MATERIAL_ALPHA_SIMPLE; + else + f->special_tiles[j].material_type = MATERIAL_ALPHA_VERTEX; + // Material flags + f->special_tiles[j].material_flags = 0; + if(f->tiledef_special[j].backface_culling) + f->special_tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING; + if(f->tiledef_special[j].animation.type == TAT_VERTICAL_FRAMES) + f->special_tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; + // Animation parameters + if(f->special_tiles[j].material_flags & + MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) + { + // Get raw texture size to determine frame count by + // aspect ratio + video::ITexture *t = tsrc->getTextureRaw(f->tiledef_special[j].name); + v2u32 size = t->getOriginalSize(); + int frame_height = (float)size.X / + (float)f->tiledef_special[j].animation.aspect_w * + (float)f->tiledef_special[j].animation.aspect_h; + int frame_count = size.Y / frame_height; + int frame_length_ms = 1000.0 * + f->tiledef_special[j].animation.length / frame_count; + f->special_tiles[j].animation_frame_count = frame_count; + f->special_tiles[j].animation_frame_length_ms = frame_length_ms; + + // If there are no frames for an animation, switch + // animation off (so that having specified an animation + // for something but not using it in the texture pack + // gives no overhead) + if(frame_count == 1){ + f->special_tiles[j].material_flags &= + ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; + } } - // Skip if should not exist - if(f->mspec_special[j].tname == "") - continue; - // Create all stuff - f->special_aps[j] = new AtlasPointer( - tsrc->getTexture(f->mspec_special[j].tname)); - f->special_materials[j] = new video::SMaterial; - f->special_materials[j]->setFlag(video::EMF_LIGHTING, false); - f->special_materials[j]->setFlag(video::EMF_BACK_FACE_CULLING, - f->mspec_special[j].backface_culling); - f->special_materials[j]->setFlag(video::EMF_BILINEAR_FILTER, false); - f->special_materials[j]->setFlag(video::EMF_FOG_ENABLE, true); - f->special_materials[j]->setTexture(0, f->special_aps[j]->atlas); - if(f->alpha != 255) - f->special_materials[j]->MaterialType = - video::EMT_TRANSPARENT_VERTEX_ALPHA; } } #endif } void serialize(std::ostream &os) { + writeU8(os, 1); // version u16 count = 0; - std::ostringstream tmp_os(std::ios::binary); + std::ostringstream os2(std::ios::binary); for(u16 i=0; i<=MAX_CONTENT; i++) { if(i == CONTENT_IGNORE || i == CONTENT_AIR) @@ -608,20 +698,27 @@ class CNodeDefManager: public IWritableNodeDefManager ContentFeatures *f = &m_content_features[i]; if(f->name == "") continue; - writeU16(tmp_os, i); - f->serialize(tmp_os); + writeU16(os2, i); + // Wrap it in a string to allow different lengths without + // strict version incompatibilities + std::ostringstream wrapper_os(std::ios::binary); + f->serialize(wrapper_os); + os2< MAX_CONTENT){ errorstream<<"ContentFeatures::deSerialize(): " <<"Too large content id: "<deSerialize(tmp_is, gamedef); + // Read it from the string wrapper + std::string wrapper = deSerializeString(is2); + std::istringstream wrapper_is(wrapper, std::ios::binary); + f->deSerialize(wrapper_is); + verbosestream<<"deserialized "<name<name != "") - m_name_id_mapping.set(i, f->name); + addNameIdMapping(i, f->name); } } private: + void addNameIdMapping(content_t i, std::string name) + { + m_name_id_mapping.set(i, name); + m_name_id_mapping_with_aliases.insert(std::make_pair(name, i)); + } +private: + // Features indexed by id ContentFeatures m_content_features[MAX_CONTENT+1]; + // 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 m_name_id_mapping_with_aliases; }; IWritableNodeDefManager* createNodeDefManager()