starting to separate "material" to "content" and "tile"
authorPerttu Ahola <celeron55@gmail.com>
Sun, 12 Dec 2010 12:33:13 +0000 (14:33 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 12 Dec 2010 12:33:13 +0000 (14:33 +0200)
minetest.conf.example
src/main.cpp
src/map.cpp
src/map.h
src/mapblock.cpp
src/mapnode.h
src/server.cpp
src/test.cpp
src/voxel.cpp
src/voxel.h

index e6c9832a5d785b009b98a392d6eba72b996882f6..1d2606ec24a81dc8f816fe3be4ea44b73465223d 100644 (file)
@@ -53,3 +53,6 @@
 #max_simultaneous_block_sends_per_client = 1
 #max_simultaneous_block_sends_server_total = 4
 
+#max_block_send_distance = 8
+#max_block_generate_distance = 5
+
index 73ef37951730f73717723ac8a7154c874e5b3065..fd91ab35c92689303f445fda0685594aa40a9116 100644 (file)
@@ -179,200 +179,19 @@ SUGG: MovingObject::move and Player::move are basically the same.
 TODO: Transfer sign texts as metadata of block and not as data of\r
       object\r
 \r
-Doing now:\r
-======================================================================\r
+SUGG: Implement a "Fast check queue" (a queue with a map for checking\r
+      if something is already in it)\r
+      - TODO: Use it in active block queue in water flowing\r
 \r
-Water dynamics pseudo-code (block = MapNode):\r
-SUGG: Create separate flag table in VoxelManipulator to allow fast\r
-clearing of "modified" flags\r
-\r
-neighborCausedPressure(pos):\r
-       pressure = 0\r
-       dirs = {down, left, right, back, front, up}\r
-       for d in dirs:\r
-               pos2 = pos + d\r
-               p = block_at(pos2).pressure\r
-               if d.Y == 1 and p > min:\r
-                       p -= 1\r
-               if d.Y == -1 and p < max:\r
-                       p += 1\r
-               if p > pressure:\r
-                       pressure = p\r
-       return pressure\r
-\r
-# This should somehow update all changed pressure values\r
-# in an unknown body of water\r
-updateWaterPressure(pos):\r
-       TODO\r
-\r
-FIXME: This goes in an indefinite loop when there is an underwater\r
-chamber like this:\r
-\r
-#111######\r
-#222##22##\r
-#33333333x<- block removed from here\r
-##########\r
-\r
-#111######\r
-#222##22##\r
-#3333333x1\r
-##########\r
-\r
-#111######\r
-#222##22##\r
-#333333x11\r
-##########\r
-\r
-#111######\r
-#222##2x##\r
-#333333333\r
-##########\r
-\r
-#111######\r
-#222##x2##\r
-#333333333\r
-##########\r
-\r
-Now, consider moving to the last block not allowed.\r
-\r
-Consider it a 3D case with a depth of 2. We're now at this situation.\r
-Note the additional blocking ## in the second depth plane.\r
-\r
-z=1         z=2\r
-#111######  #111######\r
-#222##x2##  #222##22##\r
-#333333333  #33333##33\r
-##########  ##########\r
-\r
-#111######  #111######\r
-#222##22##  #222##x2##\r
-#333333333  #33333##33\r
-##########  ##########\r
-\r
-#111######  #111######\r
-#222##22##  #222##2x##\r
-#333333333  #33333##33  \r
-##########  ##########\r
-\r
-Now there is nowhere to go, without going to an already visited block,\r
-but the pressure calculated in here from neighboring blocks is >= 2,\r
-so it is not the final ending.\r
-\r
-We will back up to a state where there is somewhere to go to.\r
-It is this state:\r
-\r
-#111######  #111######\r
-#222##22##  #222##22##\r
-#333333x33  #33333##33\r
-##########  ##########\r
-\r
-Then just go on, avoiding already visited blocks:\r
-\r
-#111######  #111######\r
-#222##22##  #222##22##\r
-#33333x333  #33333##33\r
-##########  ##########\r
-\r
-#111######  #111######\r
-#222##22##  #222##22##\r
-#3333x3333  #33333##33\r
-##########  ##########\r
-\r
-#111######  #111######\r
-#222##22##  #222##22##\r
-#333x33333  #33333##33\r
-##########  ##########\r
-\r
-#111######  #111######\r
-#222##22##  #222##22##\r
-#33x333333  #33333##33\r
-##########  ##########\r
-\r
-#111######  #111######\r
-#22x##22##  #222##22##\r
-#333333333  #33333##33\r
-##########  ##########\r
-\r
-#11x######  #111######\r
-#222##22##  #222##22##\r
-#333333333  #33333##33\r
-##########  ##########\r
-\r
-"Blob". the air bubble finally got out of the water.\r
-Then return recursively to a state where there is air next to water,\r
-clear the visit flags and feed the neighbor of the water recursively\r
-to the algorithm.\r
-\r
-#11 ######  #111######\r
-#222##22##  #222##22##\r
-#333333333x #33333##33\r
-##########  ##########\r
-\r
-#11 ######  #111######\r
-#222##22##  #222##22##\r
-#33333333x3 #33333##33\r
-##########  ##########\r
-\r
-...and so on.\r
-\r
-\r
-# removed_pos: a position that has been changed from something to air\r
-flowWater(removed_pos):\r
-       dirs = {top, left, right, back, front, bottom}\r
-       selected_dir = None\r
-       for d in dirs:\r
-               b2 = removed_pos + d\r
-\r
-               # Ignore positions that don't have water\r
-               if block_at(b2) != water:\r
-                       continue\r
-\r
-               # Ignore positions that have already been checked\r
-               if block_at(b2).checked:\r
-                       continue\r
-\r
-               # If block is at top, select it always.\r
-               if d.Y == 1:\r
-                       selected_dir = d\r
-                       break\r
-\r
-               # If block is at bottom, select it if it has enough pressure.\r
-               # >= 3 needed for stability (and sanity)\r
-               if d.Y == -1:\r
-                       if block_at(b2).pressure >= 3:\r
-                               selected_dir = d\r
-                               break\r
-                       continue\r
-               \r
-               # Else block is at some side. select it if it has enough pressure.\r
-               if block_at(b2).pressure >= 2:\r
-                       selected_dir = d\r
-                       break\r
-       \r
-       # If there is nothing to do anymore, return.\r
-       if selected_dir == None\r
-               return\r
-       \r
-       b2 = removed_pos + selected_dir\r
-       \r
-       # Move block\r
-       set_block(removed_pos, block_at(b2))\r
-       set_block(b2, air_block)\r
-       \r
-       # Update pressure\r
-       updateWaterPressure(removed_pos)\r
-       \r
-       # Flow water to the newly created empty position\r
-       flowWater(b2)\r
+TODO: Proper looking torches.\r
+      - Signs could be done in the same way?\r
 \r
-       # Check empty positions around and try flowing water to them\r
-       for d in dirs:\r
-               b3 = removed_pos + d\r
-               # Ignore positions that are not air\r
-               if block_at(b3) is not air:\r
-                       continue\r
-               flowWater(b3)\r
+Doing now:\r
+======================================================================\r
 \r
+TODO: A system for showing some nodes in some other way than cubes\r
+      - Needed for torches\r
+         - Also for signs, stairs, etc\r
 \r
 ======================================================================\r
 \r
@@ -448,7 +267,8 @@ const char *g_material_filenames[MATERIALS_COUNT] =
        "../data/leaves.png",\r
        "../data/grass_footsteps.png",\r
        "../data/mese.png",\r
-       "../data/mud.png"\r
+       "../data/mud.png",\r
+       "../data/water.png", // ocean\r
 };\r
 \r
 video::SMaterial g_materials[MATERIALS_COUNT];\r
@@ -499,6 +319,8 @@ void set_default_settings()
        g_settings.set("name", "");\r
        g_settings.set("random_input", "false");\r
        g_settings.set("client_delete_unused_sectors_timeout", "1200");\r
+       g_settings.set("max_block_send_distance", "8");\r
+       g_settings.set("max_block_generate_distance", "5");\r
 \r
        // Server stuff\r
        g_settings.set("creative_mode", "false");\r
@@ -1489,13 +1311,12 @@ int main(int argc, char *argv[])
                g_materials[i].setFlag(video::EMF_BILINEAR_FILTER, false);\r
                //g_materials[i].setFlag(video::EMF_ANISOTROPIC_FILTER, false);\r
                //g_materials[i].setFlag(video::EMF_FOG_ENABLE, true);\r
-               if(i == MATERIAL_WATER)\r
-               {\r
-                       g_materials[i].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;\r
-                       //g_materials[i].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;\r
-               }\r
        }\r
 \r
+       g_materials[MATERIAL_WATER].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;\r
+       //g_materials[MATERIAL_WATER].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;\r
+       g_materials[MATERIAL_OCEAN].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;\r
+\r
        /*g_mesh_materials[0].setTexture(0, driver->getTexture("../data/water.png"));\r
        g_mesh_materials[1].setTexture(0, driver->getTexture("../data/grass.png"));\r
        g_mesh_materials[2].setTexture(0, driver->getTexture("../data/stone.png"));\r
index 88cb0f3f75e339d45257518a67af65e2b256d1ab..1a7cd9bb9610607a2f3b1b882cfebb444651cdec 100644 (file)
@@ -1819,7 +1819,8 @@ MapBlock * ServerMap::emergeBlock(
                                // If under water level, it's water
                                if(real_y < WATER_LEVEL)
                                {
-                                       n.d = MATERIAL_WATER;
+                                       //n.d = MATERIAL_WATER;
+                                       n.d = MATERIAL_OCEAN;
                                        n.setLight(diminish_light(LIGHT_SUN, WATER_LEVEL-real_y+1));
                                }
                                // else air
@@ -2731,34 +2732,6 @@ void ClientMap::renderMap(video::IVideoDriver* driver,
        DSTACK(__FUNCTION_NAME);
 
        bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;
-#if 0
-       /*
-               Draw master heightmap mesh
-       */
-       
-       {
-               JMutexAutoLock lock(mesh_mutex);
-               if(mesh != NULL)
-               {
-                       u32 c = mesh->getMeshBufferCount();
-
-                       for(u32 i=0; i<c; i++)
-                       {
-                               scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
-                               const video::SMaterial& material = buf->getMaterial();
-                               video::IMaterialRenderer* rnd =
-                                               driver->getMaterialRenderer(material.MaterialType);
-                               bool transparent = (rnd && rnd->isTransparent());
-                               // Render transparent on transparent pass and likewise.
-                               if(transparent == is_transparent_pass)
-                               {
-                                       driver->setMaterial(buf->getMaterial());
-                                       driver->drawMeshBuffer(buf);
-                               }
-                       }
-               }
-       }
-#endif
 
        /*
                Get time for measuring timeout.
@@ -3162,7 +3135,8 @@ MapVoxelManipulator::~MapVoxelManipulator()
                        <<std::endl;
 }
 
-void MapVoxelManipulator::emerge(VoxelArea a)
+#if 1
+void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
 {
        TimeTaker timer1("emerge", g_device, &emerge_time);
 
@@ -3190,8 +3164,11 @@ void MapVoxelManipulator::emerge(VoxelArea a)
                {
                        TimeTaker timer1("emerge load", g_device, &emerge_load_time);
 
-                       dstream<<"Loading block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
-                                       <<std::endl;
+                       /*dstream<<"Loading block (caller_id="<<caller_id<<")"
+                                       <<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
+                                       <<" wanted area: ";
+                       a.print(dstream);
+                       dstream<<std::endl;*/
                        
                        MapBlock *block = m_map->getBlockNoCreate(p);
                        if(block->isDummy())
@@ -3221,6 +3198,43 @@ void MapVoxelManipulator::emerge(VoxelArea a)
 
        //dstream<<"emerge done"<<std::endl;
 }
+#endif
+
+#if 0
+void MapVoxelManipulator::emerge(VoxelArea a)
+{
+       TimeTaker timer1("emerge", g_device, &emerge_time);
+       
+       v3s16 size = a.getExtent();
+       
+       VoxelArea padded = a;
+       padded.pad(m_area.getExtent() / 4);
+       addArea(padded);
+
+       for(s16 z=0; z<size.Z; z++)
+       for(s16 y=0; y<size.Y; y++)
+       for(s16 x=0; x<size.X; x++)
+       {
+               v3s16 p(x,y,z);
+               s32 i = m_area.index(a.MinEdge + p);
+               // Don't touch nodes that have already been loaded
+               if(!(m_flags[i] & VOXELFLAG_NOT_LOADED))
+                       continue;
+               try
+               {
+                       TimeTaker timer1("emerge load", g_device, &emerge_load_time);
+                       MapNode n = m_map->getNode(a.MinEdge + p);
+                       m_data[i] = n;
+                       m_flags[i] = 0;
+               }
+               catch(InvalidPositionException &e)
+               {
+                       m_flags[i] = VOXELFLAG_INEXISTENT;
+               }
+       }
+}
+#endif
+
 
 /*
        TODO: Add an option to only update eg. water and air nodes.
@@ -3230,6 +3244,9 @@ void MapVoxelManipulator::emerge(VoxelArea a)
 void MapVoxelManipulator::blitBack
                (core::map<v3s16, MapBlock*> & modified_blocks)
 {
+       if(m_area.getExtent() == v3s16(0,0,0))
+               return;
+       
        TimeTaker timer1("blitBack", g_device);
        
        /*
index 62d1f8aee838ca2a8b28f966892639ecb9046e22..6944107dfeb57d05b2d1335698ed2926079a1263 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -603,15 +603,18 @@ public:
                m_loaded_blocks.clear();
        }
 
-       virtual void emerge(VoxelArea a);
+       virtual void emerge(VoxelArea a, s32 caller_id=-1);
 
        void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
 
 private:
        Map *m_map;
-       // bool is dummy value
-       // SUGG: How 'bout an another VoxelManipulator for storing the
-       //       information about which block is loaded?
+       /*
+               NOTE: This might be used or not
+               bool is dummy value
+               SUGG: How 'bout an another VoxelManipulator for storing the
+                     information about which block is loaded?
+       */
        core::map<v3s16, bool> m_loaded_blocks;
 };
 
index d2c3232910486771a87e3fd53b1d39ca9e837464..0f2eba8568bd6d2d5aad466635e4006c148aec67 100644 (file)
@@ -111,7 +111,7 @@ FastFace * MapBlock::makeFastFace(u8 material, u8 light, v3f p,
 
        u8 alpha = 255;
 
-       if(material == MATERIAL_WATER)
+       if(material == MATERIAL_WATER || material == MATERIAL_OCEAN)
        {
                alpha = 128;
        }
@@ -173,13 +173,14 @@ u8 MapBlock::getFaceLight(v3s16 p, v3s16 face_dir)
 
 /*
        Gets node material from any place relative to block.
-       Returns MATERIAL_AIR if doesn't exist.
+       Returns MATERIAL_IGNORE if doesn't exist or should not be drawn.
 */
 u8 MapBlock::getNodeMaterial(v3s16 p)
 {
        try{
                MapNode n = getNodeParent(p);
-               return n.d;
+               
+               return content_cube_material(n.d);
        }
        catch(InvalidPositionException &e)
        {
@@ -470,46 +471,6 @@ void MapBlock::updateMesh()
                
                collector.fillMesh(mesh_new);
 
-#if 0
-               scene::IMeshBuffer *buf = NULL;
-
-               core::list<FastFace*>::Iterator i = fastfaces_new->begin();
-
-               // MATERIAL_AIR shouldn't be used by any face
-               u8 material_in_use = MATERIAL_AIR;
-
-               for(; i != fastfaces_new->end(); i++)
-               {
-                       FastFace *f = *i;
-                       
-                       if(f->material != material_in_use || buf == NULL)
-                       {
-                               // Try to get a meshbuffer associated with the material
-                               buf = mesh_new->getMeshBuffer(g_materials[f->material]);
-                               // If not found, create one
-                               if(buf == NULL)
-                               {
-                                       // This is a "Standard MeshBuffer",
-                                       // it's a typedeffed CMeshBuffer<video::S3DVertex>
-                                       buf = new scene::SMeshBuffer();
-                                       // Set material
-                                       ((scene::SMeshBuffer*)buf)->Material = g_materials[f->material];
-                                       // Use VBO
-                                       //buf->setHardwareMappingHint(scene::EHM_STATIC);
-                                       // Add to mesh
-                                       mesh_new->addMeshBuffer(buf);
-                                       // Mesh grabbed it
-                                       buf->drop();
-                               }
-                               material_in_use = f->material;
-                       }
-                       
-                       u16 new_indices[] = {0,1,2,2,3,0};
-                       
-                       //buf->append(f->vertices, 4, indices, 6);
-               }
-#endif
-
                // Use VBO for mesh (this just would set this for ever buffer)
                //mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
                
@@ -517,8 +478,11 @@ void MapBlock::updateMesh()
                                <<"and uses "<<mesh_new->getMeshBufferCount()
                                <<" materials (meshbuffers)"<<std::endl;*/
        }
+       
+       /*
+               Clear temporary FastFaces
+       */
 
-       // TODO: Get rid of the FastFace stage
        core::list<FastFace*>::Iterator i;
        i = fastfaces_new->begin();
        for(; i != fastfaces_new->end(); i++)
@@ -528,6 +492,18 @@ void MapBlock::updateMesh()
        fastfaces_new->clear();
        delete fastfaces_new;
 
+       /*
+               Add special graphics:
+               - torches
+       */
+
+       for(s16 z=0; z<MAP_BLOCKSIZE; z++)
+       for(s16 y=0; y<MAP_BLOCKSIZE; y++)
+       for(s16 x=0; x<MAP_BLOCKSIZE; x++)
+       {
+               v3s16 p(x,y,z);
+       }
+
        /*
                Replace the mesh
        */
index 7502c42d7d3b9a4dc4572f5eeed52847656d65bb..0d65f30a48cc209993010241446199a040f147e5 100644 (file)
@@ -56,6 +56,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
        GRAVEL
          - Dynamics of gravel: if there is a drop of more than two
            blocks on any side, it will drop in there. Is this doable?
+       
+       TODO: These should be named to "content" or something like that
 */
 
 enum Material
@@ -77,6 +79,8 @@ enum Material
        MATERIAL_MESE,
 
        MATERIAL_MUD,
+
+       MATERIAL_OCEAN,
        
        // This is set to the number of the actual values in this enum
        USEFUL_MATERIAL_COUNT
@@ -88,7 +92,7 @@ enum Material
 */
 inline bool light_propagates_material(u8 m)
 {
-       return (m == MATERIAL_AIR || m == MATERIAL_LIGHT || m == MATERIAL_WATER);
+       return (m == MATERIAL_AIR || m == MATERIAL_LIGHT || m == MATERIAL_WATER || m == MATERIAL_OCEAN);
 }
 
 /*
@@ -110,7 +114,7 @@ inline u8 material_solidness(u8 m)
 {
        if(m == MATERIAL_AIR)
                return 0;
-       if(m == MATERIAL_WATER)
+       if(m == MATERIAL_WATER || m == MATERIAL_OCEAN)
                return 1;
        return 2;
 }
@@ -118,29 +122,54 @@ inline u8 material_solidness(u8 m)
 // Objects collide with walkable materials
 inline bool material_walkable(u8 m)
 {
-       return (m != MATERIAL_AIR && m != MATERIAL_WATER);
+       return (m != MATERIAL_AIR && m != MATERIAL_WATER && m != MATERIAL_OCEAN && m != MATERIAL_LIGHT);
 }
 
 // A liquid resists fast movement
 inline bool material_liquid(u8 m)
 {
-       return (m == MATERIAL_WATER);
+       return (m == MATERIAL_WATER || m == MATERIAL_OCEAN);
 }
 
 // Pointable materials can be pointed to in the map
 inline bool material_pointable(u8 m)
 {
-       return (m != MATERIAL_AIR && m != MATERIAL_WATER);
+       return (m != MATERIAL_AIR && m != MATERIAL_WATER && m != MATERIAL_OCEAN);
 }
 
 inline bool material_diggable(u8 m)
 {
-       return (m != MATERIAL_AIR && m != MATERIAL_WATER);
+       return (m != MATERIAL_AIR && m != MATERIAL_WATER && m != MATERIAL_OCEAN);
 }
 
 inline bool material_buildable_to(u8 m)
 {
-       return (m == MATERIAL_AIR || m == MATERIAL_WATER);
+       return (m == MATERIAL_AIR || m == MATERIAL_WATER || m == MATERIAL_OCEAN);
+}
+
+/*
+       As of now, input is a "material" and the output is a "material"
+*/
+inline u8 content_cube_material(u8 c)
+{
+       if(c == MATERIAL_IGNORE || c == MATERIAL_LIGHT)
+               return MATERIAL_AIR;
+       return c;
+}
+
+/*
+       Returns true for materials that form the base ground that
+       follows the main heightmap
+*/
+inline bool is_ground_material(u8 m)
+{
+       return(
+               m == MATERIAL_STONE ||
+               m == MATERIAL_GRASS ||
+               m == MATERIAL_GRASS_FOOTSTEPS ||
+               m == MATERIAL_MESE ||
+               m == MATERIAL_MUD
+       );
 }
 
 /*
@@ -168,21 +197,6 @@ inline u8 face_materials(u8 m1, u8 m2)
                return 2;
 }
 
-/*
-       Returns true for materials that form the base ground that
-       follows the main heightmap
-*/
-inline bool is_ground_material(u8 m)
-{
-       return(
-               m == MATERIAL_STONE ||
-               m == MATERIAL_GRASS ||
-               m == MATERIAL_GRASS_FOOTSTEPS ||
-               m == MATERIAL_MESE ||
-               m == MATERIAL_MUD
-       );
-}
-
 struct MapNode
 {
        //TODO: block type to differ from material
@@ -214,7 +228,9 @@ struct MapNode
 
        bool operator==(const MapNode &other)
        {
-               return (d == other.d && param == other.param);
+               return (d == other.d
+                               && param == other.param
+                               && pressure == other.pressure);
        }
 
        bool light_propagates()
index 8bcfe5216d5f7d0882013e726470c817a2243f5b..e343d5947e98f265b5e246c835e534a163d730c8 100644 (file)
@@ -196,6 +196,28 @@ void * EmergeThread::Thread()
                        {
                                MapBlock *block = i.getNode()->getValue();
                                modified_blocks.insert(block->getPos(), block);
+
+                               /*
+                                       Update water pressure.
+                                       This also adds suitable nodes to active_nodes.
+                               */
+
+                               MapVoxelManipulator v(&map);
+                               
+                               VoxelArea area(block->getPosRelative(),
+                                               block->getPosRelative() + v3s16(1,1,1)*(MAP_BLOCKSIZE-1));
+
+                               try
+                               {
+                                       v.updateAreaWaterPressure(area, m_server->m_flow_active_nodes);
+                               }
+                               catch(ProcessingLimitException &e)
+                               {
+                                       dstream<<"Processing limit reached (1)"<<std::endl;
+                               }
+                               
+                               v.blitBack(modified_blocks);
+
                        }
                        
                        /*dstream<<"lighting "<<lighting_invalidated_blocks.size()
@@ -244,12 +266,6 @@ void * EmergeThread::Thread()
                                // Remove block from sent history
                                client->SetBlocksNotSent(modified_blocks);
                        }
-                       
-                       /*if(q->peer_ids.find(client->peer_id) != NULL)
-                       {
-                               // Decrement emerge queue count of client
-                               client->BlockEmerged();
-                       }*/
                }
                
        }
@@ -348,14 +364,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
 
        //bool has_incomplete_blocks = false;
        
-       /*
-               TODO: Get this from somewhere
-       */
-       //s16 d_max = 7;
-       s16 d_max = 8;
-
-       //TODO: Get this from somewhere (probably a bigger value)
-       s16 d_max_gen = 5;
+       s16 d_max = g_settings.getS16("max_block_send_distance");
+       s16 d_max_gen = g_settings.getS16("max_block_generate_distance");
        
        //dstream<<"Starting from "<<d_start<<std::endl;
 
@@ -998,7 +1008,7 @@ void Server::AsyncRunStep()
        {
                static float counter = 0.0;
                counter += dtime;
-               if(counter >= 1.0)
+               if(counter >= 0.25 && m_flow_active_nodes.size() > 0)
                {
                
                counter = 0.0;
@@ -1011,16 +1021,7 @@ void Server::AsyncRunStep()
                        
                        MapVoxelManipulator v(&m_env.getMap());
                        
-                       /*try{
-                               v.flowWater(m_flow_active_nodes, 0, false, 20);
-                               //v.flowWater(p_under, 0, true, 100);
-                       }
-                       catch(ProcessingLimitException &e)
-                       {
-                               dstream<<"Processing limit reached"<<std::endl;
-                       }*/
-
-                       v.flowWater(m_flow_active_nodes, 0, false, 20);
+                       v.flowWater(m_flow_active_nodes, 0, false, 50);
 
                        v.blitBack(modified_blocks);
 
@@ -1059,7 +1060,7 @@ void Server::AsyncRunStep()
                        }
                }
 
-               }
+               } // interval counter
        }
        
        // Periodically print some info
@@ -1547,7 +1548,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        }
                        catch(ProcessingLimitException &e)
                        {
-                               dstream<<"Processing limit reached"<<std::endl;
+                               dstream<<"Processing limit reached (1)"<<std::endl;
                        }
                        
                        v.blitBack(modified_blocks);
@@ -1624,6 +1625,28 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                */
                                core::map<v3s16, MapBlock*> modified_blocks;
                                m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks);
+                               
+                               /*
+                                       Update water
+                               */
+                               
+                               // Update water pressure around modification
+                               // This also adds it to m_flow_active_nodes if appropriate
+
+                               MapVoxelManipulator v(&m_env.getMap());
+                               
+                               VoxelArea area(p_over-v3s16(1,1,1), p_over+v3s16(1,1,1));
+
+                               try
+                               {
+                                       v.updateAreaWaterPressure(area, m_flow_active_nodes);
+                               }
+                               catch(ProcessingLimitException &e)
+                               {
+                                       dstream<<"Processing limit reached (1)"<<std::endl;
+                               }
+                               
+                               v.blitBack(modified_blocks);
                        }
                        /*
                                Handle block object items
@@ -2019,6 +2042,10 @@ void Server::peerAdded(con::Peer *peer)
                        assert(USEFUL_MATERIAL_COUNT <= PLAYER_INVENTORY_SIZE);
                        for(u16 i=0; i<USEFUL_MATERIAL_COUNT; i++)
                        {
+                               // Skip some materials
+                               if(i == MATERIAL_OCEAN)
+                                       continue;
+
                                InventoryItem *item = new MaterialItem(i, 1);
                                player->inventory.addItem(item);
                        }
index ebefb8e32fbc3f93fc133182d1560da23dfc0e58..829aec8c15eac5098bbf8b7eaffc28f531b2690e 100644 (file)
@@ -264,11 +264,13 @@ struct TestVoxelManipulator
                s16 highest_y = -32768;
                assert(v.getWaterPressure(v3s16(7, 1, 1), highest_y, 0) == -1);
                assert(highest_y == 3);
+               /*assert(v.getWaterPressure(v3s16(7, 1, 1), highest_y, 0) == 3);
+               //assert(highest_y == 3);*/
                
                active_nodes.clear();
                active_nodes[v3s16(9,1,0)] = 1;
                //v.flowWater(active_nodes, 0, false);
-               v.flowWater(active_nodes, 0, true);
+               v.flowWater(active_nodes, 0, true, 1000);
                
                dstream<<"Final result of flowWater:"<<std::endl;
                v.print(dstream, VOXELPRINT_WATERPRESSURE);
index b85ba866642e5dd6747b771c621ed2e9460fcf4b..cdd41a14fd4a0c5bc25ebcf9425bbed8e9c5ed3c 100644 (file)
@@ -335,23 +335,26 @@ int VoxelManipulator::getWaterPressure(v3s16 p, s16 &highest_y, int recur_count)
        if(p.Y > highest_y)
                highest_y = p.Y;
        
-       recur_count++;
-       if(recur_count > 30)
+       /*if(recur_count > 1000)
                throw ProcessingLimitException
-                               ("getWaterPressure recur_count limit reached");
+                               ("getWaterPressure recur_count limit reached");*/
+       
+       if(recur_count > 10000)
+               return -1;
+       
+       recur_count++;
 
        v3s16 dirs[6] = {
                v3s16(0,1,0), // top
-               v3s16(-1,0,0), // left
-               v3s16(1,0,0), // right
-               v3s16(0,0,-1), // front
                v3s16(0,0,1), // back
+               v3s16(0,0,-1), // front
+               v3s16(1,0,0), // right
+               v3s16(-1,0,0), // left
                v3s16(0,-1,0), // bottom
        };
 
        // Load neighboring nodes
-       // TODO: A bigger area would be better
-       emerge(VoxelArea(p - v3s16(1,1,1), p + v3s16(1,1,1)));
+       emerge(VoxelArea(p - v3s16(1,1,1), p + v3s16(1,1,1)), 1);
 
        s32 i;
        for(i=0; i<6; i++)
@@ -367,14 +370,14 @@ int VoxelManipulator::getWaterPressure(v3s16 p, s16 &highest_y, int recur_count)
                        continue;
 
                int pr;
-               
-               // If at surface
-               /*if(n.pressure == 1)
+
+               // If at ocean surface
+               if(n.pressure == 1 && n.d == MATERIAL_OCEAN)
                {
                        pr = 1;
                }
                // Otherwise recurse more
-               else*/
+               else
                {
                        pr = getWaterPressure(p2, highest_y, recur_count);
                        if(pr == -1)
@@ -410,10 +413,21 @@ void VoxelManipulator::spreadWaterPressure(v3s16 p, int pr,
                core::map<v3s16, u8> &active_nodes,
                int recur_count)
 {
+       //if(recur_count > 10000)
+               /*throw ProcessingLimitException
+                               ("spreadWaterPressure recur_count limit reached");*/
+       if(recur_count > 10)
+               return;
        recur_count++;
-       if(recur_count > 10000)
-               throw ProcessingLimitException
-                               ("spreadWaterPressure recur_count limit reached");
+       
+       /*dstream<<"spreadWaterPressure: p=("
+                       <<p.X<<","<<p.Y<<","<<p.Z<<")"
+                       <<", oldpr="<<(int)m_data[m_area.index(p)].pressure
+                       <<", pr="<<pr
+                       <<", recur_count="<<recur_count
+                       <<", request_area=";
+       request_area.print(dstream);
+       dstream<<std::endl;*/
 
        m_flags[m_area.index(p)] |= VOXELFLAG_CHECKED3;
        m_data[m_area.index(p)].pressure = pr;
@@ -428,7 +442,7 @@ void VoxelManipulator::spreadWaterPressure(v3s16 p, int pr,
        };
 
        // Load neighboring nodes
-       emerge(VoxelArea(p - v3s16(1,1,1), p + v3s16(1,1,1)));
+       emerge(VoxelArea(p - v3s16(1,1,1), p + v3s16(1,1,1)), 2);
 
        s32 i;
        for(i=0; i<6; i++)
@@ -455,6 +469,7 @@ void VoxelManipulator::spreadWaterPressure(v3s16 p, int pr,
                        // If block is at top
                        if(i == 0)
                        {
+                               //if(pr >= PRESERVE_WATER_VOLUME ? 3 : 2)
                                if(pr >= 3)
                                        pressure_causes_flow = true;
                        }
@@ -466,6 +481,7 @@ void VoxelManipulator::spreadWaterPressure(v3s16 p, int pr,
                        // If block is at side
                        else
                        {
+                               //if(pr >= PRESERVE_WATER_VOLUME ? 2 : 1)
                                if(pr >= 2)
                                        pressure_causes_flow = true;
                        }
@@ -497,7 +513,10 @@ void VoxelManipulator::spreadWaterPressure(v3s16 p, int pr,
                }
                
                // Ignore if correct pressure is already set and is not on
-               // request_area
+               // request_area.
+               // Thus, request_area can be used for updating as much
+               // pressure info in some area as possible to possibly
+               // make some calls to getWaterPressure unnecessary.
                if(n.pressure == pr2 && request_area.contains(p2) == false)
                        continue;
 
@@ -512,7 +531,7 @@ void VoxelManipulator::updateAreaWaterPressure(VoxelArea a,
        TimeTaker timer("updateAreaWaterPressure", g_device,
                        &updateareawaterpressure_time);
 
-       emerge(a);
+       emerge(a, 3);
        
        bool checked2_clear = false;
        
@@ -596,20 +615,21 @@ void VoxelManipulator::updateAreaWaterPressure(VoxelArea a,
 bool VoxelManipulator::flowWater(v3s16 removed_pos,
                core::map<v3s16, u8> &active_nodes,
                int recursion_depth, bool debugprint,
-               int *counter, int counterlimit)
+               u32 stoptime)
 {
        v3s16 dirs[6] = {
                v3s16(0,1,0), // top
-               v3s16(-1,0,0), // left
-               v3s16(1,0,0), // right
                v3s16(0,0,-1), // front
                v3s16(0,0,1), // back
+               v3s16(-1,0,0), // left
+               v3s16(1,0,0), // right
                v3s16(0,-1,0), // bottom
        };
 
        recursion_depth++;
 
        v3s16 p;
+       bool from_ocean = false;
        
        // Randomize horizontal order
        static s32 cs = 0;
@@ -625,7 +645,7 @@ bool VoxelManipulator::flowWater(v3s16 removed_pos,
        TimeTaker timer1("flowWater pre", g_device, &flowwater_pre_time);
        
        // Load neighboring nodes
-       emerge(VoxelArea(removed_pos - v3s16(1,1,1), removed_pos + v3s16(1,1,1)));
+       emerge(VoxelArea(removed_pos - v3s16(1,1,1), removed_pos + v3s16(1,1,1)), 4);
        
        // Ignore incorrect removed_pos
        {
@@ -660,11 +680,13 @@ bool VoxelManipulator::flowWater(v3s16 removed_pos,
                // If block is at bottom, select it if it has enough pressure
                if(i == 5)
                {
+                       //if(n.pressure >= PRESERVE_WATER_VOLUME ? 3 : 2)
                        if(n.pressure >= 3)
                                break;
                        continue;
                }
                // Else block is at some side. Select it if it has enough pressure
+               //if(n.pressure >= PRESERVE_WATER_VOLUME ? 2 : 1)
                if(n.pressure >= 2)
                {
                        break;
@@ -675,22 +697,47 @@ bool VoxelManipulator::flowWater(v3s16 removed_pos,
        if(i==6)
                return false;
 
-       // Switch nodes at p and removed_pos
+       /*
+               Move water and bubble
+       */
+
        u8 m = m_data[m_area.index(p)].d;
        u8 f = m_flags[m_area.index(p)];
-       m_data[m_area.index(p)].d = m_data[m_area.index(removed_pos)].d;
-       m_flags[m_area.index(p)] = m_flags[m_area.index(removed_pos)];
+
+       if(m == MATERIAL_OCEAN)
+               from_ocean = true;
+
+       // Move air bubble if not taking water from ocean
+       if(from_ocean == false)
+       {
+               m_data[m_area.index(p)].d = m_data[m_area.index(removed_pos)].d;
+               m_flags[m_area.index(p)] = m_flags[m_area.index(removed_pos)];
+       }
+       
        m_data[m_area.index(removed_pos)].d = m;
        m_flags[m_area.index(removed_pos)] = f;
 
        // Mark removed_pos checked
        m_flags[m_area.index(removed_pos)] |= VOXELFLAG_CHECKED;
+
        // If block was dropped from surface, increase pressure
        if(i == 0 && m_data[m_area.index(removed_pos)].pressure == 1)
        {
                m_data[m_area.index(removed_pos)].pressure = 2;
        }
        
+       /*
+       NOTE: This does not work as-is
+       if(m == MATERIAL_OCEAN)
+       {
+               // If block was raised to surface, increase pressure of
+               // source node
+               if(i == 5 && m_data[m_area.index(p)].pressure == 1)
+               {
+                       m_data[m_area.index(p)].pressure = 2;
+               }
+       }*/
+       
        /*if(debugprint)
        {
                dstream<<"VoxelManipulator::flowWater(): Moved bubble:"<<std::endl;
@@ -720,12 +767,30 @@ bool VoxelManipulator::flowWater(v3s16 removed_pos,
        }
        
        }//timer1
-
-       // Flow water to the newly created empty position
-       flowWater(p, active_nodes, recursion_depth,
-                       debugprint, counter, counterlimit);
+       
+       //if(PRESERVE_WATER_VOLUME)
+       if(from_ocean == false)
+       {
+               // Flow water to the newly created empty position
+               /*flowWater(p, active_nodes, recursion_depth,
+                               debugprint, counter, counterlimit);*/
+               flowWater(p, active_nodes, recursion_depth,
+                               debugprint, stoptime);
+       }
+       
+       if(stoptime != 0 && g_device != NULL)
+       {
+               u32 timenow = g_device->getTimer()->getRealTime();
+               if(timenow >= stoptime ||
+                               (stoptime < 0x80000000 && timenow > 0x80000000))
+               {
+                       dstream<<"flowWater: stoptime reached"<<std::endl;
+                       throw ProcessingLimitException("flowWater stoptime reached");
+               }
+       }
        
 find_again:
+       
        // Try flowing water to empty positions around removed_pos.
        // They are checked in reverse order compared to the previous loop.
        for(s32 i=5; i>=0; i--)
@@ -745,7 +810,9 @@ find_again:
                // Flow water to node
                bool moved =
                flowWater(p, active_nodes, recursion_depth,
-                               debugprint, counter, counterlimit);
+                               debugprint, stoptime);
+               /*flowWater(p, active_nodes, recursion_depth,
+                               debugprint, counter, counterlimit);*/
                
                if(moved)
                {
@@ -754,27 +821,13 @@ find_again:
                }
        }
 
-       if(counter != NULL)
-       {
-               (*counter)++;
-               if((*counter) % 10 == 0)
-                       dstream<<"flowWater(): moved "<<(*counter)<<" nodes"
-                                       <<std::endl;
-
-               if(counterlimit != -1 && (*counter) > counterlimit)
-               {
-                       dstream<<"Counter limit reached; returning"<<std::endl;
-                       throw ProcessingLimitException("flowWater counterlimit reached");
-               }
-       }
-       
        return true;
 }
 
 void VoxelManipulator::flowWater(
                core::map<v3s16, u8> &active_nodes,
                int recursion_depth, bool debugprint,
-               int counterlimit)
+               u32 timelimit)
 {
        addarea_time = 0;
        emerge_time = 0;
@@ -783,25 +836,53 @@ void VoxelManipulator::flowWater(
        updateareawaterpressure_time = 0;
        flowwater_pre_time = 0;
 
+       if(active_nodes.size() == 0)
+       {
+               dstream<<"flowWater: no active nodes"<<std::endl;
+               return;
+       }
+
        TimeTaker timer1("flowWater (active_nodes)", g_device);
 
        dstream<<"active_nodes.size() = "<<active_nodes.size()<<std::endl;
 
-       int counter = 0;
+       //int counter = 0;
+
+       u32 stoptime = 0;
+       if(g_device != NULL)
+       {
+               stoptime = g_device->getTimer()->getRealTime() + timelimit;
+       }
+
+       // Count of handled active nodes
+       u32 handled_count = 0;
 
        try
        {
 
+       /*
+               Take random one at first
+
+               This is randomized only at the first time so that all
+               subsequent nodes will be taken at roughly the same position
+       */
+       s32 k = 0;
+       if(active_nodes.size() != 0)
+               k = (s32)rand() % (s32)active_nodes.size();
+
        // Flow water to active nodes
        for(;;)
+       //for(s32 h=0; h<1; h++)
        {
-               // Clear check flags
-               clearFlag(VOXELFLAG_CHECKED);
-               
                if(active_nodes.size() == 0)
                        break;
 
-               dstream<<"Selecting a new active_node"<<std::endl;
+               handled_count++;
+               
+               // Clear check flags
+               clearFlag(VOXELFLAG_CHECKED);
+               
+               //dstream<<"Selecting a new active_node"<<std::endl;
 
 #if 0
                // Take first one
@@ -810,9 +891,7 @@ void VoxelManipulator::flowWater(
 #endif
 
 #if 1
-               // Take random one
-               s32 k = (s32)rand() % (s32)active_nodes.size();
-               //s32 k = 0;
+               
                core::map<v3s16, u8>::Iterator
                                i = active_nodes.getIterator().getNode();
                for(s32 j=0; j<k; j++)
@@ -820,12 +899,17 @@ void VoxelManipulator::flowWater(
                        i++;
                }
                core::map<v3s16, u8>::Node *n = i.getNode();
+
+               // Decrement index if less than 0.
+               // This keeps us in existing indices always.
+               if(k > 0)
+                       k--;
 #endif
 
                v3s16 p = n->getKey();
                active_nodes.remove(p);
                flowWater(p, active_nodes, recursion_depth,
-                               debugprint, &counter, counterlimit);
+                               debugprint, stoptime);
        }
 
        }
@@ -836,11 +920,14 @@ void VoxelManipulator::flowWater(
        
        v3s16 e = m_area.getExtent();
        s32 v = m_area.getVolume();
-       dstream<<"flowWater (active): moved "<<counter<<" nodes, "
+       //dstream<<"flowWater (active): moved "<<counter<<" nodes, "
+       dstream<<"flowWater (active): "
                        <<"area ended up as "
                        <<e.X<<"x"<<e.Y<<"x"<<e.Z<<" = "<<v
+                       <<", handled a_node count: "<<handled_count
+                       <<", active_nodes.size() = "<<active_nodes.size()
                        <<std::endl;
-       
+                       
        dstream<<"addarea_time: "<<addarea_time
                        <<", emerge_time: "<<emerge_time
                        <<", emerge_load_time: "<<emerge_load_time
index 74c0a00e5dc5b0198ea9d1a7d09a89b4bc82eae3..411cf4376e3e1ce45f57faf7ff10771caebd4823 100644 (file)
@@ -428,8 +428,8 @@ public:
        bool flowWater(v3s16 removed_pos,
                        core::map<v3s16, u8> &active_nodes,
                        int recursion_depth=0,
-                       bool debugprint=false, int *counter=NULL,
-                       int counterlimit=-1
+                       bool debugprint=false,
+                       u32 stoptime=0
        );
 
        /*
@@ -446,7 +446,7 @@ public:
        void flowWater(core::map<v3s16, u8> &active_nodes,
                        int recursion_depth=0,
                        bool debugprint=false,
-                       int counterlimit=-1
+                       u32 timelimit=50
        );
 
        /*
@@ -460,7 +460,7 @@ public:
 
                If not found from source, add with VOXELFLAG_INEXISTENT
        */
-       virtual void emerge(VoxelArea a)
+       virtual void emerge(VoxelArea a, s32 caller_id=-1)
        {
                //dstream<<"emerge p=("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;
                addArea(a);