Add ignore_world_load_errors configuration option and provide better error messages
authorPerttu Ahola <celeron55@gmail.com>
Mon, 4 Jun 2012 19:34:22 +0000 (22:34 +0300)
committerPerttu Ahola <celeron55@gmail.com>
Mon, 4 Jun 2012 19:34:40 +0000 (22:34 +0300)
minetest.conf.example
src/defaultsettings.cpp
src/map.cpp
src/mapblock.cpp
src/server.cpp

index 14e3f776c80ff9e0be1909b8a169cef7d43f0c5c..7a8a2719cba2168c804162ba6889a378088c0907 100644 (file)
 # To reduce lag, block transfers are slowed down when a player is building something.
 # This determines how long they are slowed down after placing or removing a node.
 #full_block_send_enable_min_time_from_building = 2.0
-
+# Length of a server tick in dedicated server
+#dedicated_server_step = 0.05
+# Can be set to true to disable shutting down on invalid world data
+#ignore_world_load_errors = false
index ab6866cec76b042c9aa2520c607c23e12549fcfa..d0ed22c2d2db74a2229991cc6e36a62d38f429e9 100644 (file)
@@ -137,5 +137,6 @@ void set_default_settings(Settings *settings)
        settings->setDefault("server_map_save_interval", "5.3");
        settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
        settings->setDefault("dedicated_server_step", "0.05");
+       settings->setDefault("ignore_world_load_errors", "false");
 }
 
index 10dba3de94cde1a1af0bcd409daafe412fb14836..647b9fe15342348abb4be43eb8bcdead386e4ab1 100644 (file)
@@ -3378,14 +3378,20 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
        }
        catch(SerializationError &e)
        {
-               infostream<<"WARNING: Invalid block data in database "
-                               <<" (SerializationError). "
-                               <<"what()="<<e.what()
-                               <<std::endl;
-                               //" Ignoring. A new one will be generated.
-               assert(0);
+               errorstream<<"Invalid block data in database"
+                               <<" ("<<p3d.X<<","<<p3d.Y<<","<<p3d.Z<<")"
+                               <<" (SerializationError): "<<e.what()<<std::endl;
+               
+               // TODO: Block should be marked as invalid in memory so that it is
+               // not touched but the game can run
 
-               // TODO: Copy to a backup database.
+               if(g_settings->getBool("ignore_world_load_errors")){
+                       errorstream<<"Ignoring block load error. Duck and cover! "
+                                       <<"(ignore_world_load_errors)"<<std::endl;
+               } else {
+                       throw SerializationError("Invalid block data in database");
+                       //assert(0);
+               }
        }
 }
 
index ed49f7b8225bb6578e182e26918083c9e1c7e550..907be05eb3dfa959ffdaff347e5056a84e32b42d 100644 (file)
@@ -35,6 +35,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapblock_mesh.h"
 #endif
 
+#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
+
 /*
        MapBlock
 */
@@ -634,6 +636,8 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
 {
        if(!ser_ver_supported(version))
                throw VersionMismatchException("ERROR: MapBlock format not supported");
+       
+       TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())<<std::endl);
 
        m_day_night_differs_expired = false;
 
@@ -652,6 +656,8 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
        /*
                Bulk node data
        */
+       TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
+                       <<": Bulk node data"<<std::endl);
        u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
        u8 content_width = readU8(is);
        u8 params_width = readU8(is);
@@ -665,6 +671,8 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
        /*
                NodeMetadata
        */
+       TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
+                       <<": Node metadata"<<std::endl);
        // Ignore errors
        try{
                std::ostringstream oss(std::ios_base::binary);
@@ -680,7 +688,8 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
        catch(SerializationError &e)
        {
                errorstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error"
-                               <<" while deserializing node metadata: "<<e.what()<<std::endl;
+                               <<" while deserializing node metadata at ("
+                               <<PP(getPos())<<": "<<e.what()<<std::endl;
        }
 
        /*
@@ -689,21 +698,33 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
        if(disk)
        {
                // Node timers
-               if(version >= 23)
+               if(version >= 23){
+                       TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
+                                       <<": Node timers"<<std::endl);
                        m_node_timers.deSerialize(is);
+               }
 
                // Static objects
+               TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
+                               <<": Static objects"<<std::endl);
                m_static_objects.deSerialize(is);
                
                // Timestamp
+               TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
+                               <<": Timestamp"<<std::endl);
                setTimestamp(readU32(is));
                m_disk_timestamp = m_timestamp;
                
                // Dynamically re-set ids based on node names
+               TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
+                               <<": NameIdMapping"<<std::endl);
                NameIdMapping nimap;
                nimap.deSerialize(is);
                correctBlockNodeIds(&nimap, data, m_gamedef);
        }
+               
+       TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
+                       <<": Done."<<std::endl);
 }
 
 /*
index fbeff83bfe459b368b2bd9b20258fa6f7d1df436..f336fadc8f4253118d459586871de93257d9459e 100644 (file)
@@ -164,6 +164,8 @@ void * EmergeThread::Thread()
        BEGIN_DEBUG_EXCEPTION_HANDLER
 
        bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
+
+       v3s16 last_tried_pos(-32768,-32768,-32768); // For error output
        
        /*
                Get block info from queue, emerge them and send them
@@ -181,6 +183,8 @@ void * EmergeThread::Thread()
 
                v3s16 &p = q->pos;
                v2s16 p2d(p.X,p.Z);
+               
+               last_tried_pos = p;
 
                /*
                        Do not generate over-limit
@@ -377,8 +381,23 @@ void * EmergeThread::Thread()
        }
        catch(VersionMismatchException &e)
        {
-               m_server->setAsyncFatalError(std::string(
-                               "World data version mismatch (server-side) (world probably saved by a newer version of Minetest): ")+e.what());
+               std::ostringstream err;
+               err<<"World data version mismatch in MapBlock "<<PP(last_tried_pos)<<std::endl;
+               err<<"----"<<std::endl;
+               err<<"\""<<e.what()<<"\""<<std::endl;
+               err<<"See debug.txt."<<std::endl;
+               err<<"World probably saved by a newer version of Minetest."<<std::endl;
+               m_server->setAsyncFatalError(err.str());
+       }
+       catch(SerializationError &e)
+       {
+               std::ostringstream err;
+               err<<"Invalid data in MapBlock "<<PP(last_tried_pos)<<std::endl;
+               err<<"----"<<std::endl;
+               err<<"\""<<e.what()<<"\""<<std::endl;
+               err<<"See debug.txt."<<std::endl;
+               err<<"You can ignore this using [ignore_world_load_errors = true]."<<std::endl;
+               m_server->setAsyncFatalError(err.str());
        }
 
        END_DEBUG_EXCEPTION_HANDLER(errorstream)