aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Collision/Management/IVMapManager.h3
-rw-r--r--src/common/Collision/Management/VMapManager2.cpp20
-rw-r--r--src/common/Collision/Management/VMapManager2.h2
-rw-r--r--src/common/Collision/Maps/MapTree.cpp72
-rw-r--r--src/common/Collision/Maps/MapTree.h7
-rw-r--r--src/server/game/Maps/Map.cpp4
-rw-r--r--src/tools/mmaps_generator/PathGenerator.cpp2
-rw-r--r--src/tools/mmaps_generator/TerrainBuilder.cpp4
-rw-r--r--src/tools/vmap4_assembler/TileAssembler.cpp23
-rw-r--r--src/tools/vmap4_extractor/vmapexport.cpp4
10 files changed, 82 insertions, 59 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);
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index bd844ac6329..e0fb4370fea 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -190,6 +190,10 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy)
TC_LOG_ERROR("maps", "VMap file '%s' couldn't be loaded", (sWorld->GetDataPath() + "vmaps/" + name).c_str());
TC_LOG_ERROR("maps", "This is because the version of the VMap file and the version of this module are different, please re-extract the maps with the tools compiled with this module.");
return false;
+ case VMAP::LoadResult::ReadFromFileFailed:
+ TC_LOG_ERROR("maps", "VMap file '%s' couldn't be loaded", (sWorld->GetDataPath() + "vmaps/" + name).c_str());
+ TC_LOG_ERROR("maps", "This is because VMAP files are corrupted, please re-extract the maps with the tools compiled with this module.");
+ return false;
}
}
}
diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp
index 0873885d114..2589ae9c875 100644
--- a/src/tools/mmaps_generator/PathGenerator.cpp
+++ b/src/tools/mmaps_generator/PathGenerator.cpp
@@ -319,6 +319,8 @@ std::unordered_map<uint32, std::vector<uint32>> LoadMap(std::string const& local
mapData.emplace(std::piecewise_construct, std::forward_as_tuple(record.GetId()), std::forward_as_tuple());
int16 parentMapId = int16(record.GetUInt16("ParentMapID"));
+ if (parentMapId < 0)
+ parentMapId = int16(record.GetUInt16("CosmeticParentMapID"));
if (parentMapId != -1)
mapData[parentMapId].push_back(record.GetId());
}
diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp
index fda251e8402..a5c77fefe31 100644
--- a/src/tools/mmaps_generator/TerrainBuilder.cpp
+++ b/src/tools/mmaps_generator/TerrainBuilder.cpp
@@ -638,12 +638,12 @@ namespace MMAP
bool TerrainBuilder::loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData)
{
VMapManager2* vmapManager = static_cast<VMapManager2*>(VMapFactory::createOrGetVMapManager());
- int result = vmapManager->loadSingleMap(mapID, "vmaps", tileX, tileY);
+ LoadResult result = vmapManager->loadSingleMap(mapID, "vmaps", tileX, tileY);
bool retval = false;
do
{
- if (result == VMAP_LOAD_RESULT_ERROR)
+ if (result != LoadResult::Success)
break;
InstanceTreeMap instanceTrees;
diff --git a/src/tools/vmap4_assembler/TileAssembler.cpp b/src/tools/vmap4_assembler/TileAssembler.cpp
index a29cb3a516d..ed9406eca96 100644
--- a/src/tools/vmap4_assembler/TileAssembler.cpp
+++ b/src/tools/vmap4_assembler/TileAssembler.cpp
@@ -76,7 +76,7 @@ namespace VMAP
printf("Calculating model bounds for map %u...\n", data.MapId);
for (auto entry = data.UniqueEntries.begin(); entry != data.UniqueEntries.end(); ++entry)
{
- // M2 models don't have a bound set in WDT/ADT placement data, i still think they're not used for LoS at all on retail
+ // M2 models don't have a bound set in WDT/ADT placement data, they're not used for LoS but are needed for pathfinding
if (entry->second.flags & MOD_M2)
if (!calculateTransformedBound(entry->second))
continue;
@@ -133,7 +133,6 @@ namespace VMAP
for (uint32 i = 0; i < mapSpawnsSize; ++i)
{
if (success && fwrite(&mapSpawns[i]->ID, sizeof(uint32), 1, mapfile) != 1) success = false;
- if (success && fwrite(&i, sizeof(uint32), 1, mapfile) != 1) success = false;
}
fclose(mapfile);
@@ -292,7 +291,7 @@ namespace VMAP
for (uint32 g = 0; g < groups; ++g)
{
GroupModel_Raw& raw_group = raw_model.groupsArray[g];
- groupsArray.push_back(GroupModel(raw_group.mogpflags, raw_group.GroupWMOID, raw_group.bounds ));
+ groupsArray.push_back(GroupModel(raw_group.mogpflags, raw_group.GroupWMOID, raw_group.bounds));
groupsArray.back().setMeshData(raw_group.vertexArray, raw_group.triangles);
groupsArray.back().setLiquidData(raw_group.liquid);
}
@@ -353,21 +352,9 @@ namespace VMAP
spawnedModelFiles.insert(model_name);
AABox bounds;
- bool boundEmpty = true;
- for (uint32 g = 0; g < raw_model.groupsArray.size(); ++g)
- {
- std::vector<Vector3>& vertices = raw_model.groupsArray[g].vertexArray;
-
- uint32 nvectors = vertices.size();
- for (uint32 i = 0; i < nvectors; ++i)
- {
- Vector3& v = vertices[i];
- if (boundEmpty)
- bounds = AABox(v, v), boundEmpty = false;
- else
- bounds.merge(v);
- }
- }
+ for (GroupModel_Raw const& groupModel : raw_model.groupsArray)
+ for (G3D::Vector3 const& vertice : groupModel.vertexArray)
+ bounds.merge(vertice);
if (bounds.isEmpty())
{
diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp
index d3407beb895..4b7239bf53e 100644
--- a/src/tools/vmap4_extractor/vmapexport.cpp
+++ b/src/tools/vmap4_extractor/vmapexport.cpp
@@ -502,6 +502,10 @@ int main(int argc, char ** argv)
map.ParentMapID = int16(record.GetUInt16("ParentMapID"));
map.Name = record.GetString("MapName");
map.Directory = record.GetString("Directory");
+
+ if (map.ParentMapID < 0)
+ map.ParentMapID = int16(record.GetUInt16("CosmeticParentMapID"));
+
if (map.ParentMapID >= 0)
maps_that_are_parents.insert(map.ParentMapID);