diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/Collision/Management/IVMapManager.h | 3 | ||||
| -rw-r--r-- | src/common/Collision/Management/VMapManager2.cpp | 20 | ||||
| -rw-r--r-- | src/common/Collision/Management/VMapManager2.h | 2 | ||||
| -rw-r--r-- | src/common/Collision/Maps/MapTree.cpp | 72 | ||||
| -rw-r--r-- | src/common/Collision/Maps/MapTree.h | 7 |
5 files changed, 65 insertions, 39 deletions
diff --git a/src/common/Collision/Management/IVMapManager.h b/src/common/Collision/Management/IVMapManager.h index 3d760082e28..e779878b8e0 100644 --- a/src/common/Collision/Management/IVMapManager.h +++ b/src/common/Collision/Management/IVMapManager.h @@ -43,7 +43,8 @@ namespace VMAP { Success, FileNotFound, - VersionMismatch + VersionMismatch, + ReadFromFileFailed }; #define VMAP_INVALID_HEIGHT -100000.0f // for check diff --git a/src/common/Collision/Management/VMapManager2.cpp b/src/common/Collision/Management/VMapManager2.cpp index 88494d0a0c7..ed4e5535250 100644 --- a/src/common/Collision/Management/VMapManager2.cpp +++ b/src/common/Collision/Management/VMapManager2.cpp @@ -104,14 +104,21 @@ namespace VMAP int result = VMAP_LOAD_RESULT_IGNORED; if (isMapLoadingEnabled()) { - if (loadSingleMap(mapId, basePath, x, y)) + LoadResult parentLoadResult = loadSingleMap(mapId, basePath, x, y); + if (parentLoadResult == LoadResult::Success || parentLoadResult == LoadResult::FileNotFound) { - result = VMAP_LOAD_RESULT_OK; + if (parentLoadResult == LoadResult::Success) + result = VMAP_LOAD_RESULT_OK; + // else VMAP_LOAD_RESULT_IGNORED + auto childMaps = iChildMapData.find(mapId); if (childMaps != iChildMapData.end()) for (uint32 childMapId : childMaps->second) - if (!loadSingleMap(childMapId, basePath, x, y)) + { + LoadResult childLoadResult = loadSingleMap(childMapId, basePath, x, y); + if (childLoadResult != LoadResult::Success && childLoadResult != LoadResult::FileNotFound) result = VMAP_LOAD_RESULT_ERROR; + } } else result = VMAP_LOAD_RESULT_ERROR; @@ -121,7 +128,7 @@ namespace VMAP } // load one tile (internal use only) - bool VMapManager2::loadSingleMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY) + LoadResult VMapManager2::loadSingleMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY) { auto instanceTree = iInstanceMapTrees.find(mapId); if (instanceTree == iInstanceMapTrees.end()) @@ -137,10 +144,11 @@ namespace VMAP { std::string mapFileName = getMapFileName(mapId); StaticMapTree* newTree = new StaticMapTree(mapId, basePath); - if (!newTree->InitMap(mapFileName)) + LoadResult treeInitResult = newTree->InitMap(mapFileName); + if (treeInitResult != LoadResult::Success) { delete newTree; - return false; + return treeInitResult; } instanceTree->second = newTree; } diff --git a/src/common/Collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h index 76253faded4..024c1619a2f 100644 --- a/src/common/Collision/Management/VMapManager2.h +++ b/src/common/Collision/Management/VMapManager2.h @@ -102,7 +102,7 @@ namespace VMAP void InitializeThreadUnsafe(std::unordered_map<uint32, std::vector<uint32>> const& mapData); int loadMap(char const* pBasePath, unsigned int mapId, int x, int y) override; - bool loadSingleMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY); + LoadResult loadSingleMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY); void unloadMap(unsigned int mapId, int x, int y) override; void unloadSingleMap(uint32 mapId, int x, int y); diff --git a/src/common/Collision/Maps/MapTree.cpp b/src/common/Collision/Maps/MapTree.cpp index 04f914fb4f1..7249a0cf1a2 100644 --- a/src/common/Collision/Maps/MapTree.cpp +++ b/src/common/Collision/Maps/MapTree.cpp @@ -240,6 +240,7 @@ namespace VMAP TileFileOpenResult result; result.Name = basePath + getTileFileName(mapID, tileX, tileY); result.File = fopen(result.Name.c_str(), "rb"); + result.UsedMapId = mapID; if (!result.File) { int32 parentMapId = vm->getParentMapId(mapID); @@ -247,6 +248,7 @@ namespace VMAP { result.Name = basePath + getTileFileName(parentMapId, tileX, tileY); result.File = fopen(result.Name.c_str(), "rb"); + result.UsedMapId = parentMapId; if (result.File) break; @@ -302,44 +304,47 @@ namespace VMAP //========================================================= - bool StaticMapTree::InitMap(std::string const& fname) + LoadResult StaticMapTree::InitMap(std::string const& fname) { TC_LOG_DEBUG("maps", "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str()); - bool success = false; std::string fullname = iBasePath + fname; FILE* rf = fopen(fullname.c_str(), "rb"); if (!rf) - return false; + return LoadResult::FileNotFound; + LoadResult result = LoadResult::Success; char chunk[8]; - if (readChunk(rf, chunk, VMAP_MAGIC, 8) && + if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) + result = LoadResult::VersionMismatch; + + if (result == LoadResult::Success && readChunk(rf, chunk, "NODE", 4) && iTree.readFromFile(rf)) { iNTreeValues = iTree.primCount(); iTreeValues = new ModelInstance[iNTreeValues]; - success = true; + result = LoadResult::Success; } - if (success) + if (result == LoadResult::Success) { - success = readChunk(rf, chunk, "SIDX", 4); + result = readChunk(rf, chunk, "SIDX", 4) ? LoadResult::Success : LoadResult::ReadFromFileFailed; uint32 spawnIndicesSize = 0; uint32 spawnId; - uint32 spawnIndex; - if (success && fread(&spawnIndicesSize, sizeof(uint32), 1, rf) != 1) success = false; - for (uint32 i = 0; i < spawnIndicesSize && success; ++i) + if (result == LoadResult::Success && fread(&spawnIndicesSize, sizeof(uint32), 1, rf) != 1) + result = LoadResult::ReadFromFileFailed; + for (uint32 i = 0; i < spawnIndicesSize && result == LoadResult::Success; ++i) { - if (fread(&spawnId, sizeof(uint32), 1, rf) == 1 && fread(&spawnIndex, sizeof(uint32), 1, rf) == 1) - iSpawnIndices[spawnId] = spawnIndex; + if (fread(&spawnId, sizeof(uint32), 1, rf) == 1) + iSpawnIndices[spawnId] = i; else - success = false; + result = LoadResult::ReadFromFileFailed; } } fclose(rf); - return success; + return result; } //========================================================= @@ -358,31 +363,31 @@ namespace VMAP //========================================================= - bool StaticMapTree::LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm) + LoadResult StaticMapTree::LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm) { if (!iTreeValues) { TC_LOG_ERROR("misc", "StaticMapTree::LoadMapTile() : tree has not been initialized [%u, %u]", tileX, tileY); - return false; + return LoadResult::ReadFromFileFailed; } - bool result = true; + LoadResult result = LoadResult::FileNotFound; TileFileOpenResult fileResult = OpenMapTileFile(iBasePath, iMapID, tileX, tileY, vm); if (fileResult.File) { char chunk[8]; + result = LoadResult::Success; if (!readChunk(fileResult.File, chunk, VMAP_MAGIC, 8)) - result = false; + result = LoadResult::VersionMismatch; uint32 numSpawns = 0; - if (result && fread(&numSpawns, sizeof(uint32), 1, fileResult.File) != 1) - result = false; - for (uint32 i = 0; i < numSpawns && result; ++i) + if (result == LoadResult::Success && fread(&numSpawns, sizeof(uint32), 1, fileResult.File) != 1) + result = LoadResult::ReadFromFileFailed; + for (uint32 i = 0; i < numSpawns && result == LoadResult::Success; ++i) { // read model spawns ModelSpawn spawn; - result = ModelSpawn::readFromFile(fileResult.File, spawn); - if (result) + if (ModelSpawn::readFromFile(fileResult.File, spawn)) { // acquire model instance WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags); @@ -416,8 +421,19 @@ namespace VMAP #endif } } - else - result = false; + else if (int32(iMapID) == fileResult.UsedMapId) + { + // unknown parent spawn might appear in because it overlaps multiple tiles + // in case the original tile is swapped but its neighbour is now (adding this spawn) + // we want to not mark it as loading error and just skip that model + TC_LOG_ERROR("maps", "StaticMapTree::LoadMapTile() : invalid tree element (spawn %u) referenced in tile %s by map %u", spawn.ID, fileResult.Name.c_str(), iMapID); + result = LoadResult::ReadFromFileFailed; + } + } + else + { + TC_LOG_ERROR("maps", "StaticMapTree::LoadMapTile() : cannot read model from file (spawn index %u) referenced in tile %s by map %u", i, fileResult.Name.c_str(), iMapID); + result = LoadResult::ReadFromFileFailed; } } iLoadedTiles[packTileID(tileX, tileY)] = true; @@ -465,9 +481,7 @@ namespace VMAP // update tree auto spawnIndex = iSpawnIndices.find(spawn.ID); - if (spawnIndex == iSpawnIndices.end()) - result = false; - else + if (spawnIndex != iSpawnIndices.end()) { uint32 referencedNode = spawnIndex->second; if (!iLoadedSpawns.count(referencedNode)) @@ -478,6 +492,8 @@ namespace VMAP iLoadedSpawns.erase(referencedNode); } } + else if (int32(iMapID) == fileResult.UsedMapId) // logic documented in StaticMapTree::LoadMapTile + result = false; } } fclose(fileResult.File); diff --git a/src/common/Collision/Maps/MapTree.h b/src/common/Collision/Maps/MapTree.h index d2012ea7a30..8b96164bd7c 100644 --- a/src/common/Collision/Maps/MapTree.h +++ b/src/common/Collision/Maps/MapTree.h @@ -61,8 +61,9 @@ namespace VMAP struct TileFileOpenResult { - FILE* File; std::string Name; + FILE* File; + int32 UsedMapId; }; private: @@ -84,9 +85,9 @@ namespace VMAP bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const; bool GetLocationInfo(const G3D::Vector3 &pos, LocationInfo &info) const; - bool InitMap(std::string const& fname); + LoadResult InitMap(std::string const& fname); void UnloadMap(VMapManager2* vm); - bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); + LoadResult LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); uint32 numLoadedTiles() const { return uint32(iLoadedTiles.size()); } void getModelInstances(ModelInstance* &models, uint32 &count); |
