Tools/mmaps_generator: Use unique_ptr to manage memory

This commit is contained in:
Shauren
2025-10-25 10:57:46 +02:00
parent 03e2aa6737
commit 82e8c26831
5 changed files with 76 additions and 135 deletions
@@ -17,6 +17,7 @@
#include "IntermediateValues.h"
#include "Log.h"
#include "Memory.h"
#include "StringFormat.h"
namespace MMAP
@@ -37,10 +38,9 @@ namespace MMAP
auto debugWrite = [&](char const* extension, auto const* data)
{
std::string fileName = Trinity::StringFormat("meshes/{:04}{:02}{:02}.{}", mapID, tileY, tileX, extension);
if (FILE* file = fopen(fileName.c_str(), "wb"))
if (auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(), "wb")))
{
this->debugWrite(file, data);
fclose(file);
this->debugWrite(file.get(), data);
}
else
TC_LOG_ERROR("maps.mmapgen.debug", "{}: [{:04}-{:02},{:02}] Failed to open {} for writing!", strerror(errno), mapID, tileX, tileY, fileName);
@@ -193,7 +193,7 @@ namespace MMAP
std::string objFileName;
objFileName = Trinity::StringFormat("meshes/map{:04}{:02}{:02}.obj", mapID, tileY, tileX);
FILE* objFile = fopen(objFileName.c_str(), "wb");
auto objFile = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(objFileName.c_str(), "wb"));
if (!objFile)
{
TC_LOG_ERROR("maps.mmapgen.debug", "{}: Failed to open {} for writing!", strerror(errno), objFileName);
@@ -214,18 +214,16 @@ namespace MMAP
int triCount = allTris.size() / 3;
for (int i = 0; i < allVerts.size() / 3; i++)
fprintf(objFile, "v %f %f %f\n", verts[i*3], verts[i*3 + 1], verts[i*3 + 2]);
fprintf(objFile.get(), "v %f %f %f\n", verts[i*3], verts[i*3 + 1], verts[i*3 + 2]);
for (int i = 0; i < allTris.size() / 3; i++)
fprintf(objFile, "f %i %i %i\n", tris[i*3] + 1, tris[i*3 + 1] + 1, tris[i*3 + 2] + 1);
fclose(objFile);
fprintf(objFile.get(), "f %i %i %i\n", tris[i*3] + 1, tris[i*3 + 1] + 1, tris[i*3 + 2] + 1);
TC_LOG_INFO("maps.mmapgen.debug", "[Map {:04}] [{:02},{:02}]: Writing debug output object file...", mapID, tileY, tileX);
objFileName = Trinity::StringFormat("meshes/map{:04}.map", mapID);
objFile = fopen(objFileName.c_str(), "wb");
objFile.reset(fopen(objFileName.c_str(), "wb"));
if (!objFile)
{
TC_LOG_ERROR("maps.mmapgen.debug", "{}: Failed to open {} for writing!", strerror(errno), objFileName);
@@ -233,25 +231,22 @@ namespace MMAP
}
char b = '\0';
fwrite(&b, sizeof(char), 1, objFile);
fclose(objFile);
fwrite(&b, sizeof(char), 1, objFile.get());
objFileName = Trinity::StringFormat("meshes/map{:04}{:02}{:02}.mesh", mapID, tileY, tileX);
objFile = fopen(objFileName.c_str(), "wb");
objFile.reset(fopen(objFileName.c_str(), "wb"));
if (!objFile)
{
TC_LOG_ERROR("maps.mmapgen.debug", "{}: Failed to open {} for writing!", strerror(errno), objFileName);
return;
}
fwrite(&vertCount, sizeof(int), 1, objFile);
fwrite(verts, sizeof(float), vertCount*3, objFile);
fflush(objFile);
fwrite(&vertCount, sizeof(int), 1, objFile.get());
fwrite(verts, sizeof(float), vertCount*3, objFile.get());
fflush(objFile.get());
fwrite(&triCount, sizeof(int), 1, objFile);
fwrite(tris, sizeof(int), triCount*3, objFile);
fflush(objFile);
fclose(objFile);
fwrite(&triCount, sizeof(int), 1, objFile.get());
fwrite(tris, sizeof(int), triCount*3, objFile.get());
fflush(objFile.get());
}
}
+18 -54
View File
@@ -92,9 +92,6 @@ namespace MMAP
_queue.Cancel();
for (auto& builder : m_tileBuilders)
delete builder;
m_tileBuilders.clear();
m_tiles.clear();
}
@@ -252,11 +249,10 @@ namespace MMAP
{
TC_LOG_INFO("maps.mmapgen", "Using {} threads to generate mmaps", m_threads);
m_tileBuilders.resize(m_threads);
for (unsigned int i = 0; i < m_threads; ++i)
{
m_tileBuilders.push_back(new MapTileBuilder(this, m_maxWalkableAngle, m_maxWalkableAngleNotSteep,
m_tileBuilders[i].reset(new MapTileBuilder(this, m_maxWalkableAngle, m_maxWalkableAngleNotSteep,
m_skipLiquid, m_bigBaseUnit, m_debugOutput, &m_offMeshConnections));
}
if (mapID)
{
@@ -278,86 +274,57 @@ namespace MMAP
_queue.Cancel();
for (auto& builder : m_tileBuilders)
delete builder;
m_tileBuilders.clear();
}
/**************************************************************************/
void MapBuilder::buildMeshFromFile(char* name)
{
FILE* file = fopen(name, "rb");
auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(name, "rb"));
if (!file)
return;
TC_LOG_INFO("maps.mmapgen", "Building mesh from file");
int tileX, tileY, mapId;
if (fread(&mapId, sizeof(int), 1, file) != 1)
{
fclose(file);
if (fread(&mapId, sizeof(int), 1, file.get()) != 1)
return;
}
if (fread(&tileX, sizeof(int), 1, file) != 1)
{
fclose(file);
if (fread(&tileX, sizeof(int), 1, file.get()) != 1)
return;
}
if (fread(&tileY, sizeof(int), 1, file) != 1)
{
fclose(file);
if (fread(&tileY, sizeof(int), 1, file.get()) != 1)
return;
}
dtNavMesh* navMesh = nullptr;
buildNavMesh(mapId, navMesh);
if (!navMesh)
{
TC_LOG_ERROR("maps.mmapgen", "Failed creating navmesh!");
fclose(file);
return;
}
uint32 verticesCount, indicesCount;
if (fread(&verticesCount, sizeof(uint32), 1, file) != 1)
{
fclose(file);
if (fread(&verticesCount, sizeof(uint32), 1, file.get()) != 1)
return;
}
if (fread(&indicesCount, sizeof(uint32), 1, file) != 1)
{
fclose(file);
if (fread(&indicesCount, sizeof(uint32), 1, file.get()) != 1)
return;
}
float* verts = new float[verticesCount];
if (fread(verts, sizeof(float), verticesCount, file) != verticesCount)
{
fclose(file);
delete[] verts;
std::unique_ptr<float[]> verts = std::make_unique<float[]>(verticesCount);
if (fread(verts.get(), sizeof(float), verticesCount, file.get()) != verticesCount)
return;
}
int* inds = new int[indicesCount];
if (fread(inds, sizeof(int), indicesCount, file) != indicesCount)
{
fclose(file);
delete[] verts;
delete[] inds;
std::unique_ptr<int[]> inds = std::make_unique<int[]>(indicesCount);
if (fread(inds.get(), sizeof(int), indicesCount, file.get()) != indicesCount)
return;
}
MeshData data;
for (uint32 i = 0; i < verticesCount; ++i)
data.solidVerts.append(verts[i]);
delete[] verts;
for (uint32 i = 0; i < indicesCount; ++i)
data.solidTris.append(inds[i]);
delete[] inds;
TerrainBuilder::cleanVertices(data.solidVerts, data.solidTris);
// get bounds of current tile
@@ -368,7 +335,6 @@ namespace MMAP
MapTileBuilder tileBuilder(this, m_maxWalkableAngle, m_maxWalkableAngleNotSteep,
m_skipLiquid, m_bigBaseUnit, m_debugOutput, &m_offMeshConnections);
tileBuilder.buildMoveMapTile(mapId, tileX, tileY, data, bmin, bmax, navMesh);
fclose(file);
}
/**************************************************************************/
@@ -500,7 +466,7 @@ namespace MMAP
std::string fileName = Trinity::StringFormat("mmaps/{:04}.mmap", mapID);
FILE* file = fopen(fileName.c_str(), "wb");
auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(), "wb"));
if (!file)
{
dtFreeNavMesh(navMesh);
@@ -510,8 +476,7 @@ namespace MMAP
}
// now that we know navMesh params are valid, we can write them to file
fwrite(&navMeshParams, sizeof(dtNavMeshParams), 1, file);
fclose(file);
fwrite(&navMeshParams, sizeof(dtNavMeshParams), 1, file.get());
}
/**************************************************************************/
@@ -603,13 +568,12 @@ namespace MMAP
bool MapTileBuilder::shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY) const
{
std::string fileName = Trinity::StringFormat("mmaps/{:04}{:02}{:02}.mmtile", mapID, tileY, tileX);
FILE* file = fopen(fileName.c_str(), "rb");
auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(), "rb"));
if (!file)
return false;
MmapTileHeader header;
int count = fread(&header, sizeof(MmapTileHeader), 1, file);
fclose(file);
int count = fread(&header, sizeof(MmapTileHeader), 1, file.get());
if (count != 1)
return false;
+1 -1
View File
@@ -140,7 +140,7 @@ namespace MMAP
uint32 m_totalTiles;
std::atomic<uint32> m_totalTilesProcessed;
std::vector<TileBuilder*> m_tileBuilders;
std::vector<std::unique_ptr<TileBuilder>> m_tileBuilders;
ProducerConsumerQueue<TileInfo> _queue;
std::atomic<bool> _cancelationToken;
};
+25 -36
View File
@@ -20,6 +20,7 @@
#include "MapDefines.h"
#include "MapTree.h"
#include "MMapDefines.h"
#include "Memory.h"
#include "ModelInstance.h"
#include "StringFormat.h"
#include "Util.h"
@@ -80,14 +81,14 @@ namespace MMAP
{
std::string mapFileName = Trinity::StringFormat("maps/{:04}_{:02}_{:02}.map", mapID, tileY, tileX);
FILE* mapFile = fopen(mapFileName.c_str(), "rb");
auto mapFile = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(mapFileName.c_str(), "rb"));
if (!mapFile)
{
int32 parentMapId = vmapManager->getParentMapId(mapID);
while (!mapFile && parentMapId != -1)
{
mapFileName = Trinity::StringFormat("maps/{:04}_{:02}_{:02}.map", parentMapId, tileY, tileX);
mapFile = fopen(mapFileName.c_str(), "rb");
mapFile.reset(fopen(mapFileName.c_str(), "rb"));
parentMapId = vmapManager->getParentMapId(mapID);
}
}
@@ -96,20 +97,19 @@ namespace MMAP
return false;
map_fileheader fheader;
if (fread(&fheader, sizeof(map_fileheader), 1, mapFile) != 1 ||
if (fread(&fheader, sizeof(map_fileheader), 1, mapFile.get()) != 1 ||
fheader.versionMagic != MapVersionMagic)
{
fclose(mapFile);
TC_LOG_ERROR("maps.mmapgen", "{} is the wrong version, please extract new .map files", mapFileName);
return false;
}
map_heightHeader hheader;
fseek(mapFile, fheader.heightMapOffset, SEEK_SET);
fseek(mapFile.get(), fheader.heightMapOffset, SEEK_SET);
bool haveTerrain = false;
bool haveLiquid = false;
if (fread(&hheader, sizeof(map_heightHeader), 1, mapFile) == 1)
if (fread(&hheader, sizeof(map_heightHeader), 1, mapFile.get()) == 1)
{
haveTerrain = !hheader.flags.HasFlag(map_heightHeaderFlags::NoHeight);
haveLiquid = fheader.liquidMapOffset && !m_skipLiquid;
@@ -117,10 +117,7 @@ namespace MMAP
// no data in this map file
if (!haveTerrain && !haveLiquid)
{
fclose(mapFile);
return false;
}
// data used later
uint8 holes[16][16][8] = { };
@@ -141,8 +138,8 @@ namespace MMAP
uint8 v9[V9_SIZE_SQ];
uint8 v8[V8_SIZE_SQ];
size_t count = 0;
count += fread(v9, sizeof(uint8), V9_SIZE_SQ, mapFile);
count += fread(v8, sizeof(uint8), V8_SIZE_SQ, mapFile);
count += fread(v9, sizeof(uint8), V9_SIZE_SQ, mapFile.get());
count += fread(v8, sizeof(uint8), V8_SIZE_SQ, mapFile.get());
if (count != expected)
TC_LOG_ERROR("maps.mmapgen", "TerrainBuilder::loadMap: Failed to read {} height data expected {}, read {}", mapFileName, expected, count);
@@ -159,8 +156,8 @@ namespace MMAP
uint16 v9[V9_SIZE_SQ];
uint16 v8[V8_SIZE_SQ];
size_t count = 0;
count += fread(v9, sizeof(uint16), V9_SIZE_SQ, mapFile);
count += fread(v8, sizeof(uint16), V8_SIZE_SQ, mapFile);
count += fread(v9, sizeof(uint16), V9_SIZE_SQ, mapFile.get());
count += fread(v8, sizeof(uint16), V8_SIZE_SQ, mapFile.get());
if (count != expected)
TC_LOG_ERROR("maps.mmapgen", "TerrainBuilder::loadMap: Failed to read {} height data expected {}, read {}", mapFileName, expected, count);
@@ -175,8 +172,8 @@ namespace MMAP
else
{
size_t count = 0;
count += fread(V9, sizeof(float), V9_SIZE_SQ, mapFile);
count += fread(V8, sizeof(float), V8_SIZE_SQ, mapFile);
count += fread(V9, sizeof(float), V9_SIZE_SQ, mapFile.get());
count += fread(V8, sizeof(float), V8_SIZE_SQ, mapFile.get());
if (count != expected)
TC_LOG_ERROR("maps.mmapgen", "TerrainBuilder::loadMap: Failed to read {} height data expected {}, read {}", mapFileName, expected, count);
}
@@ -185,8 +182,8 @@ namespace MMAP
if (fheader.holesSize != 0)
{
memset(holes, 0, fheader.holesSize);
fseek(mapFile, fheader.holesOffset, SEEK_SET);
if (fread(holes, fheader.holesSize, 1, mapFile) != 1)
fseek(mapFile.get(), fheader.holesOffset, SEEK_SET);
if (fread(holes, fheader.holesSize, 1, mapFile.get()) != 1)
TC_LOG_ERROR("maps.mmapgen", "TerrainBuilder::loadMap: Failed to read {} holes data expected {}, read {}", mapFileName, 1, 0);
}
@@ -229,17 +226,17 @@ namespace MMAP
if (haveLiquid)
{
map_liquidHeader lheader;
fseek(mapFile, fheader.liquidMapOffset, SEEK_SET);
if (fread(&lheader, sizeof(map_liquidHeader), 1, mapFile) != 1)
fseek(mapFile.get(), fheader.liquidMapOffset, SEEK_SET);
if (fread(&lheader, sizeof(map_liquidHeader), 1, mapFile.get()) != 1)
TC_LOG_ERROR("maps.mmapgen", "TerrainBuilder::loadMap: Failed to read {} liquid header expected {}, read {}", mapFileName, 1, 0);
float* liquid_map = nullptr;
std::unique_ptr<float[]> liquid_map;
if (!lheader.flags.HasFlag(map_liquidHeaderFlags::NoType))
{
if (fread(liquid_entry, sizeof(liquid_entry), 1, mapFile) != 1)
if (fread(liquid_entry, sizeof(liquid_entry), 1, mapFile.get()) != 1)
TC_LOG_ERROR("maps.mmapgen", "TerrainBuilder::loadMap: Failed to read {} liquid id expected {}, read {}", mapFileName, 1, 0);
if (fread(liquid_flags, sizeof(liquid_flags), 1, mapFile) != 1)
if (fread(liquid_flags, sizeof(liquid_flags), 1, mapFile.get()) != 1)
TC_LOG_ERROR("maps.mmapgen", "TerrainBuilder::loadMap: Failed to read {} liquid flags expected {}, read {}", mapFileName, 1, 0);
}
else
@@ -251,11 +248,10 @@ namespace MMAP
if (!lheader.flags.HasFlag(map_liquidHeaderFlags::NoHeight))
{
uint32 toRead = lheader.width * lheader.height;
liquid_map = new float [toRead];
if (fread(liquid_map, sizeof(float), toRead, mapFile) != toRead)
liquid_map = std::make_unique<float[]>(toRead);
if (fread(liquid_map.get(), sizeof(float), toRead, mapFile.get()) != toRead)
{
TC_LOG_ERROR("maps.mmapgen", "TerrainBuilder::loadMap: Failed to read {} liquid header expected {}, read {}", mapFileName, toRead, 0);
delete[] liquid_map;
liquid_map = nullptr;
}
}
@@ -284,7 +280,7 @@ namespace MMAP
continue;
}
getLiquidCoord(i, j, xoffset, yoffset, coord, liquid_map);
getLiquidCoord(i, j, xoffset, yoffset, coord, liquid_map.get());
meshData.liquidVerts.append(coord[0]);
meshData.liquidVerts.append(coord[2]);
meshData.liquidVerts.append(coord[1]);
@@ -301,8 +297,6 @@ namespace MMAP
}
}
delete[] liquid_map;
int indices[] = { 0, 0, 0 };
int loopStart = 0, loopEnd = 0, loopInc = 0, triInc = BOTTOM-TOP;
getLoopVars(portion, loopStart, loopEnd, loopInc);
@@ -320,8 +314,6 @@ namespace MMAP
}
}
fclose(mapFile);
// now that we have gathered the data, we can figure out which parts to keep:
// liquid above ground, ground above liquid
int loopStart = 0, loopEnd = 0, loopInc = 0, tTriCount = 4;
@@ -338,11 +330,11 @@ namespace MMAP
// make a copy of liquid vertices
// used to pad right-bottom frame due to lost vertex data at extraction
float* lverts_copy = nullptr;
std::unique_ptr<float[]> lverts_copy;
if (meshData.liquidVerts.size())
{
lverts_copy = new float[meshData.liquidVerts.size()];
memcpy(lverts_copy, lverts, sizeof(float)*meshData.liquidVerts.size());
lverts_copy = std::make_unique<float[]>(meshData.liquidVerts.size());
memcpy(lverts_copy.get(), lverts, sizeof(float)* meshData.liquidVerts.size());
}
getLoopVars(portion, loopStart, loopEnd, loopInc);
@@ -471,9 +463,6 @@ namespace MMAP
}
}
if (lverts_copy)
delete [] lverts_copy;
return meshData.solidTris.size() || meshData.liquidTris.size();
}
+17 -24
View File
@@ -19,6 +19,7 @@
#include "IntermediateValues.h"
#include "Log.h"
#include "MMapDefines.h"
#include "Memory.h"
#include "PathCommon.h"
#include "StringFormat.h"
#include "VMapManager.h"
@@ -169,7 +170,7 @@ namespace MMAP
rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height);
// allocate subregions : tiles
Tile* tiles = new Tile[TILES_PER_MAP * TILES_PER_MAP];
std::unique_ptr<Tile[]> tiles = std::make_unique<Tile[]>(TILES_PER_MAP * TILES_PER_MAP);
// Initialize per tile config.
rcConfig tileCfg = config;
@@ -177,8 +178,8 @@ namespace MMAP
tileCfg.height = config.tileSize + config.borderSize * 2;
// merge per tile poly and detail meshes
rcPolyMesh** pmmerge = new rcPolyMesh * [TILES_PER_MAP * TILES_PER_MAP];
rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail * [TILES_PER_MAP * TILES_PER_MAP];
std::unique_ptr<rcPolyMesh*[]> pmmerge = std::make_unique<rcPolyMesh*[]>(TILES_PER_MAP * TILES_PER_MAP);
std::unique_ptr<rcPolyMeshDetail*[]> dmmerge = std::make_unique<rcPolyMeshDetail*[]>(TILES_PER_MAP * TILES_PER_MAP);
int nmerge = 0;
// build all tiles
for (int y = 0; y < TILES_PER_MAP; ++y)
@@ -214,12 +215,11 @@ namespace MMAP
* any area above that will get RC_NULL_AREA (unwalkable), then call rcMarkWalkableTriangles with 55 to set NAV_AREA_GROUND
* on anything below 55 . Players and idle Creatures can use NAV_AREA_GROUND, while Creatures in combat can use NAV_AREA_GROUND_STEEP.
*/
unsigned char* triFlags = new unsigned char[tTriCount];
memset(triFlags, NAV_AREA_GROUND_STEEP, tTriCount * sizeof(unsigned char));
rcClearUnwalkableTriangles(&m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags);
rcMarkWalkableTriangles(&m_rcContext, tileCfg.walkableSlopeAngleNotSteep, tVerts, tVertCount, tTris, tTriCount, triFlags, NAV_AREA_GROUND);
rcRasterizeTriangles(&m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb);
delete[] triFlags;
std::unique_ptr<unsigned char[]> triFlags = std::make_unique<unsigned char[]>(tTriCount);
memset(triFlags.get(), NAV_AREA_GROUND_STEEP, tTriCount * sizeof(unsigned char));
rcClearUnwalkableTriangles(&m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags.get());
rcMarkWalkableTriangles(&m_rcContext, tileCfg.walkableSlopeAngleNotSteep, tVerts, tVertCount, tTris, tTriCount, triFlags.get(), NAV_AREA_GROUND);
rcRasterizeTriangles(&m_rcContext, tVerts, tVertCount, tTris, triFlags.get(), tTriCount, *tile.solid, config.walkableClimb);
rcFilterLowHangingWalkableObstacles(&m_rcContext, config.walkableClimb, *tile.solid);
rcFilterLedgeSpans(&m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid);
@@ -303,28 +303,22 @@ namespace MMAP
if (!iv.polyMesh)
{
TC_LOG_ERROR("maps.mmapgen", "{} alloc iv.polyMesh FAILED!", tileString);
delete[] pmmerge;
delete[] dmmerge;
delete[] tiles;
return;
}
rcMergePolyMeshes(&m_rcContext, pmmerge, nmerge, *iv.polyMesh);
rcMergePolyMeshes(&m_rcContext, pmmerge.get(), nmerge, *iv.polyMesh);
iv.polyMeshDetail = rcAllocPolyMeshDetail();
if (!iv.polyMeshDetail)
{
TC_LOG_ERROR("maps.mmapgen", "{} alloc m_dmesh FAILED!", tileString);
delete[] pmmerge;
delete[] dmmerge;
delete[] tiles;
return;
}
rcMergePolyMeshDetails(&m_rcContext, dmmerge, nmerge, *iv.polyMeshDetail);
rcMergePolyMeshDetails(&m_rcContext, dmmerge.get(), nmerge, *iv.polyMeshDetail);
// free things up
delete[] pmmerge;
delete[] dmmerge;
delete[] tiles;
pmmerge = nullptr;
dmmerge = nullptr;
tiles = nullptr;
// set polygons as walkable
// TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off
@@ -433,7 +427,7 @@ namespace MMAP
// file output
std::string fileName = Trinity::StringFormat("mmaps/{:04}{:02}{:02}.mmtile", mapID, tileY, tileX);
FILE* file = fopen(fileName.c_str(), "wb");
auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(), "wb"));
if (!file)
{
TC_LOG_ERROR("maps.mmapgen", "{}: [Map {:04}] Failed to open {} for writing!", strerror(errno), mapID, fileName);
@@ -447,11 +441,10 @@ namespace MMAP
MmapTileHeader header;
header.usesLiquids = m_terrainBuilder.usesLiquids();
header.size = uint32(navDataSize);
fwrite(&header, sizeof(MmapTileHeader), 1, file);
fwrite(&header, sizeof(MmapTileHeader), 1, file.get());
// write data
fwrite(navData, sizeof(unsigned char), navDataSize, file);
fclose(file);
fwrite(navData, sizeof(unsigned char), navDataSize, file.get());
// now that tile is written to disk, we can unload it
navMesh->removeTile(tileRef, nullptr, nullptr);