diff options
-rw-r--r-- | minetest.conf.example | 5 | ||||
-rw-r--r-- | src/defaultsettings.cpp | 1 | ||||
-rw-r--r-- | src/map.cpp | 20 | ||||
-rw-r--r-- | src/mapblock.cpp | 25 | ||||
-rw-r--r-- | src/server.cpp | 23 |
5 files changed, 62 insertions, 12 deletions
diff --git a/minetest.conf.example b/minetest.conf.example index 14e3f776c..7a8a2719c 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -178,4 +178,7 @@ # 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 diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index ab6866cec..d0ed22c2d 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -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"); } diff --git a/src/map.cpp b/src/map.cpp index 10dba3de9..647b9fe15 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -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); + } } } diff --git a/src/mapblock.cpp b/src/mapblock.cpp index ed49f7b82..907be05eb 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -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); } /* diff --git a/src/server.cpp b/src/server.cpp index fbeff83bf..f336fadc8 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -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) |