X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmapblock.cpp;h=2f6a4b850116522e8bd98c855f91819425ae8ec4;hb=7efe89ff584b2c0338dcede4c1e08504d0158780;hp=e828183969d7d4df7901faf7c54958977301ae41;hpb=fa64103aa87a8f0f2a3351bb4a54e93e8ade1082;p=dragonfireclient.git diff --git a/src/mapblock.cpp b/src/mapblock.cpp index e82818396..2f6a4b850 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -19,12 +19,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock.h" #include "map.h" -// For g_materials +// For g_settings #include "main.h" #include "light.h" #include - /* MapBlock */ @@ -32,16 +31,20 @@ with this program; if not, write to the Free Software Foundation, Inc., MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy): m_parent(parent), m_pos(pos), - changed(true), + m_modified(MOD_STATE_WRITE_NEEDED), is_underground(false), + m_lighting_expired(true), m_day_night_differs(false), - m_objects(this) + m_generated(false), + m_objects(this), + m_timestamp(BLOCK_TIMESTAMP_UNDEFINED), + m_usage_timer(BLOCK_TIMESTAMP_UNDEFINED) { data = NULL; if(dummy == false) reallocate(); - m_spawn_timer = -10000; + //m_spawn_timer = -10000; #ifndef SERVER m_mesh_expired = false; @@ -130,437 +133,9 @@ MapNode MapBlock::getNodeParentNoEx(v3s16 p) } } -/* - Parameters must consist of air and !air. - Order doesn't matter. - - If either of the nodes doesn't exist, light is 0. - - parameters: - daynight_ratio: 0...1000 - n: getNodeParent(p) - n2: getNodeParent(p + face_dir) - face_dir: axis oriented unit vector from p to p2 -*/ -u8 MapBlock::getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2, - v3s16 face_dir) -{ - try{ - u8 light; - u8 l1 = n.getLightBlend(daynight_ratio); - u8 l2 = n2.getLightBlend(daynight_ratio); - if(l1 > l2) - light = l1; - else - light = l2; - - // Make some nice difference to different sides - - /*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1) - light = diminish_light(diminish_light(light)); - else if(face_dir.X == -1 || face_dir.Z == -1) - light = diminish_light(light);*/ - - if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1) - light = diminish_light(diminish_light(light)); - else if(face_dir.Z == 1 || face_dir.Z == -1) - light = diminish_light(light); - - return light; - } - catch(InvalidPositionException &e) - { - return 0; - } -} - #ifndef SERVER -void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p, - v3s16 dir, v3f scale, v3f posRelative_f, - core::array &dest) -{ - FastFace face; - - // Position is at the center of the cube. - v3f pos = p * BS; - posRelative_f *= BS; - - v3f vertex_pos[4]; - // If looking towards z+, this is the face that is behind - // the center point, facing towards z+. - vertex_pos[0] = v3f( BS/2,-BS/2,BS/2); - vertex_pos[1] = v3f(-BS/2,-BS/2,BS/2); - vertex_pos[2] = v3f(-BS/2, BS/2,BS/2); - vertex_pos[3] = v3f( BS/2, BS/2,BS/2); - - if(dir == v3s16(0,0,1)) - { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateXZBy(0); - } - else if(dir == v3s16(0,0,-1)) - { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateXZBy(180); - } - else if(dir == v3s16(1,0,0)) - { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateXZBy(-90); - } - else if(dir == v3s16(-1,0,0)) - { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateXZBy(90); - } - else if(dir == v3s16(0,1,0)) - { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateYZBy(-90); - } - else if(dir == v3s16(0,-1,0)) - { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateYZBy(90); - } - - for(u16 i=0; i<4; i++) - { - vertex_pos[i].X *= scale.X; - vertex_pos[i].Y *= scale.Y; - vertex_pos[i].Z *= scale.Z; - vertex_pos[i] += pos + posRelative_f; - } - - f32 abs_scale = 1.; - if (scale.X < 0.999 || scale.X > 1.001) abs_scale = scale.X; - else if(scale.Y < 0.999 || scale.Y > 1.001) abs_scale = scale.Y; - else if(scale.Z < 0.999 || scale.Z > 1.001) abs_scale = scale.Z; - - v3f zerovector = v3f(0,0,0); - - //u8 li = decode_light(light); - u8 li = light; - - u8 alpha = 255; - - if(tile.id == TILE_WATER) - { - alpha = 128; - } - - video::SColor c = video::SColor(alpha,li,li,li); - - face.vertices[0] = video::S3DVertex(vertex_pos[0], zerovector, c, - core::vector2d(0,1)); - face.vertices[1] = video::S3DVertex(vertex_pos[1], zerovector, c, - core::vector2d(abs_scale,1)); - face.vertices[2] = video::S3DVertex(vertex_pos[2], zerovector, c, - core::vector2d(abs_scale,0)); - face.vertices[3] = video::S3DVertex(vertex_pos[3], zerovector, c, - core::vector2d(0,0)); - - face.tile = tile; - //DEBUG - //f->tile = TILE_STONE; - - dest.push_back(face); - //return f; -} - -/* - Gets node tile from any place relative to block. - Returns TILE_NODE if doesn't exist or should not be drawn. -*/ -TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir) -{ - // DEBUG - u16 *ptr = NULL; - *ptr = 7357; - - TileSpec spec; - - /*//DEBUG - { - spec.id = TILE_STONE; - return spec; - }*/ - - spec.feature = TILEFEAT_NONE; - //spec.id = TILE_STONE; - spec.id = mn.getTile(face_dir); - - /* - Check temporary modifications on this node - */ - core::map::Node *n; - n = m_temp_mods.find(p); - - // If modified - if(n != NULL) - { - struct NodeMod mod = n->getValue(); - if(mod.type == NODEMOD_CHANGECONTENT) - { - spec.id = content_tile(mod.param, face_dir); - } - if(mod.type == NODEMOD_CRACK) - { - spec.feature = TILEFEAT_CRACK; - spec.param.crack.progression = mod.param; - } - } - - return spec; -} - -u8 MapBlock::getNodeContent(v3s16 p, MapNode mn) -{ - /* - Check temporary modifications on this node - */ - core::map::Node *n; - n = m_temp_mods.find(p); - - // If modified - if(n != NULL) - { - struct NodeMod mod = n->getValue(); - if(mod.type == NODEMOD_CHANGECONTENT) - { - // Overrides content - return mod.param; - } - if(mod.type == NODEMOD_CRACK) - { - /* - Content doesn't change. - - face_contents works just like it should, because - there should not be faces between differently cracked - nodes. - - If a semi-transparent node is cracked in front an - another one, it really doesn't matter whether there - is a cracked face drawn in between or not. - */ - } - } - - return mn.d; -} - -/* - startpos: - translate_dir: unit vector with only one of x, y or z - face_dir: unit vector with only one of x, y or z -*/ -void MapBlock::updateFastFaceRow( - u32 daynight_ratio, - v3f posRelative_f, - v3s16 startpos, - u16 length, - v3s16 translate_dir, - v3f translate_dir_f, - v3s16 face_dir, - v3f face_dir_f, - core::array &dest) -{ - v3s16 p = startpos; - - u16 continuous_tiles_count = 0; - - MapNode n0 = getNodeParentNoEx(p); - MapNode n1 = getNodeParentNoEx(p + face_dir); - - u8 light = getFaceLight(daynight_ratio, n0, n1, face_dir); - - TileSpec tile0 = getNodeTile(n0, p, face_dir); - TileSpec tile1 = getNodeTile(n1, p + face_dir, -face_dir); - - for(u16 j=0; j indices; - core::array vertices; -}; - -class MeshCollector -{ -public: - void append( - video::SMaterial material, - const video::S3DVertex* const vertices, - u32 numVertices, - const u16* const indices, - u32 numIndices - ) - { - PreMeshBuffer *p = NULL; - for(u32 i=0; ivertices.size(); - for(u32 i=0; i 65535) - { - dstream<<"FIXME: Meshbuffer ran out of indices"<indices.push_back(j); - } - for(u32 i=0; ivertices.push_back(vertices[i]); - } - } - - void fillMesh(scene::SMesh *mesh) - { - /*dstream<<"Filling mesh with "< - scene::SMeshBuffer *buf = new scene::SMeshBuffer(); - // Set material - buf->Material = p.material; - //((scene::SMeshBuffer*)buf)->Material = p.material; - // Use VBO - //buf->setHardwareMappingHint(scene::EHM_STATIC); - // Add to mesh - mesh->addMeshBuffer(buf); - // Mesh grabbed it - buf->drop(); - - buf->append(p.vertices.pointer(), p.vertices.size(), - p.indices.pointer(), p.indices.size()); - } - } - -private: - core::array m_prebuffers; -}; - +#if 1 void MapBlock::updateMesh(u32 daynight_ratio) { #if 0 @@ -573,232 +148,23 @@ void MapBlock::updateMesh(u32 daynight_ratio) return; } #endif - - // 4-21ms - //TimeTaker timer1("updateMesh()", g_device); - core::array fastfaces_new; + MeshMakeData data; + data.fill(daynight_ratio, this); - v3f posRelative_f(getPosRelative().X, getPosRelative().Y, - getPosRelative().Z); // floating point conversion + scene::SMesh *mesh_new = makeMapBlockMesh(&data); /* - We are including the faces of the trailing edges of the block. - This means that when something changes, the caller must - also update the meshes of the blocks at the leading edges. - - NOTE: This is the slowest part of this method. - */ - - { - // Lock this, as m_temp_mods will be used directly - JMutexAutoLock lock(m_temp_mods_mutex); - - /* - Go through every y,z and get top faces in rows of x+ - */ - for(s16 y=0; y 0) - { - MeshCollector collector; - - for(u32 i=0; igetTexture( - TextureSpec(name, path, mod)); - - video::SMaterial material = tile_material_get(f.tile.id); - material.setTexture(0, texture); - - collector.append(material, f.vertices, 4, indices, 6); - } - else - { - // No such feature - assert(0); - } - } - - collector.fillMesh(mesh_new); - - // Use VBO for mesh (this just would set this for ever buffer) - // This will lead to infinite memory usage because or irrlicht. - //mesh_new->setHardwareMappingHint(scene::EHM_STATIC); - - /*std::cout<<"MapBlock has "<getSize()<<" faces " - <<"and uses "<getMeshBufferCount() - <<" materials (meshbuffers)"<append(vertices, 4, indices, 6); - - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - buf->getMaterial().MaterialType - = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - if(dir == v3s16(0,-1,0)) - buf->getMaterial().setTexture(0, - g_irrlicht->getTexture("../data/torch_on_floor.png")); - else if(dir == v3s16(0,1,0)) - buf->getMaterial().setTexture(0, - g_irrlicht->getTexture("../data/torch_on_ceiling.png")); - // For backwards compatibility - else if(dir == v3s16(0,0,0)) - buf->getMaterial().setTexture(0, - g_irrlicht->getTexture("../data/torch_on_floor.png")); - else - buf->getMaterial().setTexture(0, - g_irrlicht->getTexture("../data/torch.png")); - - // Add to mesh - mesh_new->addMeshBuffer(buf); - buf->drop(); - } - } - - /* - Do some stuff to the mesh - */ - - mesh_new->recalculateBoundingBox(); - - /* - Delete new mesh if it is empty + Replace the mesh */ - if(mesh_new->getMeshBufferCount() == 0) - { - mesh_new->drop(); - mesh_new = NULL; - } + replaceMesh(mesh_new); - /* - Replace the mesh - */ +} +#endif +void MapBlock::replaceMesh(scene::SMesh *mesh_new) +{ mesh_mutex.Lock(); //scene::SMesh *mesh_old = mesh[daynight_i]; @@ -835,41 +201,31 @@ void MapBlock::updateMesh(u32 daynight_ratio) } mesh_mutex.Unlock(); - - //std::cout<<"added "<= 0 && first_i <= DAYNIGHT_CACHE_COUNT); - updateMesh(first_i); - for(s32 i=0; i & light_sources) +bool MapBlock::propagateSunlight(core::map & light_sources, + bool remove_light, bool *black_air_left) { // Whether the sunlight at the top of the bottom block is valid bool block_below_is_valid = true; @@ -880,12 +236,13 @@ bool MapBlock::propagateSunlight(core::map & light_sources) { for(s16 z=0; z & light_sources) { no_sunlight = true; } - - // NOTE: As of now, it just would make everything dark. + else + { + MapNode n = getNode(v3s16(x, MAP_BLOCKSIZE-1, z)); + //if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) + if(content_features(n.d).sunlight_propagates == false) + { + no_sunlight = true; + } + } + // NOTE: As of now, this just would make everything dark. // No sunlight here //no_sunlight = true; } +#endif +#if 0 // Doesn't work; nothing gets light. + bool no_sunlight = true; + bool no_top_block = false; + // Check if node above block has sunlight + try{ + MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z)); + if(n.getLight(LIGHTBANK_DAY) == LIGHT_SUN) + { + no_sunlight = false; + } + } + catch(InvalidPositionException &e) + { + no_top_block = true; + } +#endif /*std::cout<<"("<= 10) { - // Uncompress and set pressure data + // Uncompress and set param2 data std::ostringstream os(std::ios_base::binary); decompress(is, os, version); std::string s = os.str(); @@ -1317,7 +747,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version) ("MapBlock::deSerialize: invalid format"); for(u32 i=0; i= 18) + m_generated = (flags & 0x08) ? false : true; // Uncompress data std::ostringstream os(std::ios_base::binary); @@ -1337,7 +770,8 @@ void MapBlock::deSerialize(std::istream &is, u8 version) std::string s = os.str(); if(s.size() != nodecount*3) throw SerializationError - ("MapBlock::deSerialize: invalid format"); + ("MapBlock::deSerialize: decompress resulted in size" + " other than nodecount*3"); // Set contents for(u32 i=0; i= 14) + { + // Ignore errors + try{ + if(version <= 15) + { + std::string data = deSerializeString(is); + std::istringstream iss(data, std::ios_base::binary); + m_node_metadata.deSerialize(iss); + } + else + { + //std::string data = deSerializeLongString(is); + std::ostringstream oss(std::ios_base::binary); + decompressZlib(is, oss); + std::istringstream iss(oss.str(), std::ios_base::binary); + m_node_metadata.deSerialize(iss); + } + } + catch(SerializationError &e) + { + dstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error" + <<" while deserializing node metadata"<d<= 9) + { + //serializeObjects(os, version); // DEPRECATED + // count=0 + writeU16(os, 0); + } + + // Versions up from 15 have static objects. + if(version >= 15) + { + m_static_objects.serialize(os); + } + + // Timestamp + if(version >= 17) + { + writeU32(os, getTimestamp()); + } +} + +void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version) +{ + /* + Versions up from 9 have block objects. + */ + if(version >= 9) + { + updateObjects(is, version, NULL, 0); + } + + /* + Versions up from 15 have static objects. + */ + if(version >= 15) + { + m_static_objects.deSerialize(is); + } + + // Timestamp + if(version >= 17) + { + setTimestamp(readU32(is)); + } + else + { + setTimestamp(BLOCK_TIMESTAMP_UNDEFINED); } }