Fix /shutdown or ^C no longer causing server exit
[oweals/minetest.git] / src / map.cpp
index a1502befa5ff0a7aa161b062dae82c340ce01d2d..689112c7d3102b40c6a228a16e6b935243d53316 100644 (file)
@@ -1157,6 +1157,72 @@ void Map::removeNodeTimer(v3s16 p)
        block->m_node_timers.remove(p_rel);
 }
 
+bool Map::isOccluded(v3s16 p0, v3s16 p1, float step, float stepfac,
+               float start_off, float end_off, u32 needed_count)
+{
+       float d0 = (float)BS * p0.getDistanceFrom(p1);
+       v3s16 u0 = p1 - p0;
+       v3f uf = v3f(u0.X, u0.Y, u0.Z) * BS;
+       uf.normalize();
+       v3f p0f = v3f(p0.X, p0.Y, p0.Z) * BS;
+       u32 count = 0;
+       for(float s=start_off; s<d0+end_off; s+=step){
+               v3f pf = p0f + uf * s;
+               v3s16 p = floatToInt(pf, BS);
+               MapNode n = getNodeNoEx(p);
+               const ContentFeatures &f = m_nodedef->get(n);
+               if(f.drawtype == NDT_NORMAL){
+                       // not transparent, see ContentFeature::updateTextures
+                       count++;
+                       if(count >= needed_count)
+                               return true;
+               }
+               step *= stepfac;
+       }
+       return false;
+}
+
+bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes) {
+       v3s16 cpn = block->getPos() * MAP_BLOCKSIZE;
+       cpn += v3s16(MAP_BLOCKSIZE / 2, MAP_BLOCKSIZE / 2, MAP_BLOCKSIZE / 2);
+       float step = BS * 1;
+       float stepfac = 1.1;
+       float startoff = BS * 1;
+       // The occlusion search of 'isOccluded()' must stop short of the target
+       // point by distance 'endoff' (end offset) to not enter the target mapblock.
+       // For the 8 mapblock corners 'endoff' must therefore be the maximum diagonal
+       // of a mapblock, because we must consider all view angles.
+       // sqrt(1^2 + 1^2 + 1^2) = 1.732
+       float endoff = -BS * MAP_BLOCKSIZE * 1.732050807569;
+       v3s16 spn = cam_pos_nodes;
+       s16 bs2 = MAP_BLOCKSIZE / 2 + 1;
+       // to reduce the likelihood of falsely occluded blocks
+       // require at least two solid blocks
+       // this is a HACK, we should think of a more precise algorithm
+       u32 needed_count = 2;
+
+       return (
+               // For the central point of the mapblock 'endoff' can be halved
+               isOccluded(spn, cpn,
+                       step, stepfac, startoff, endoff / 2.0f, needed_count) &&
+               isOccluded(spn, cpn + v3s16(bs2,bs2,bs2),
+                       step, stepfac, startoff, endoff, needed_count) &&
+               isOccluded(spn, cpn + v3s16(bs2,bs2,-bs2),
+                       step, stepfac, startoff, endoff, needed_count) &&
+               isOccluded(spn, cpn + v3s16(bs2,-bs2,bs2),
+                       step, stepfac, startoff, endoff, needed_count) &&
+               isOccluded(spn, cpn + v3s16(bs2,-bs2,-bs2),
+                       step, stepfac, startoff, endoff, needed_count) &&
+               isOccluded(spn, cpn + v3s16(-bs2,bs2,bs2),
+                       step, stepfac, startoff, endoff, needed_count) &&
+               isOccluded(spn, cpn + v3s16(-bs2,bs2,-bs2),
+                       step, stepfac, startoff, endoff, needed_count) &&
+               isOccluded(spn, cpn + v3s16(-bs2,-bs2,bs2),
+                       step, stepfac, startoff, endoff, needed_count) &&
+               isOccluded(spn, cpn + v3s16(-bs2,-bs2,-bs2),
+                       step, stepfac, startoff, endoff, needed_count));
+}
+
 /*
        ServerMap
 */
@@ -2372,13 +2438,6 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
                        throw SerializationError("ServerMap::loadBlock(): Failed"
                                        " to read MapBlock version");
 
-               /*u32 block_size = MapBlock::serializedLength(version);
-               SharedBuffer<u8> data(block_size);
-               is.read((char*)*data, block_size);*/
-
-               // This will always return a sector because we're the server
-               //MapSector *sector = emergeSector(p2d);
-
                MapBlock *block = NULL;
                bool created_new = false;
                block = sector->getBlockNoCreateNoEx(p3d.Y);