mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-23 07:40:14 +00:00
Fix release packaging and macOS stack overflow crash
- Fix StormLib package name: libstormlib-dev → libstorm-dev (correct Ubuntu package name) across all CI workflows and extract_assets.sh - Build StormLib from source on Windows CI (no MSYS2 package exists), ensuring asset_extract.exe is included in release archives - Update extract_assets.sh/.ps1 to prefer pre-built asset_extract binary next to the script (release archives) before trying build dir - Move ADTTerrain allocations from stack to heap in prepareTile() to fix stack overflow on macOS (worker threads default to 512 KB stack, two ADTTerrain structs ≈ 560 KB exceeded that)
This commit is contained in:
parent
624744da86
commit
8fe53171eb
6 changed files with 76 additions and 37 deletions
|
|
@ -269,9 +269,11 @@ std::shared_ptr<PendingTile> TerrainManager::prepareTile(int x, int y) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Parse ADT
|
||||
pipeline::ADTTerrain terrain = pipeline::ADTLoader::load(adtData);
|
||||
if (!terrain.isLoaded()) {
|
||||
// Parse ADT — allocate on heap to avoid stack overflow on macOS
|
||||
// (ADTTerrain contains std::array<MapChunk,256> ≈ 280 KB; macOS worker
|
||||
// threads default to 512 KB stack, so two on-stack copies would overflow)
|
||||
auto terrainPtr = std::make_unique<pipeline::ADTTerrain>(pipeline::ADTLoader::load(adtData));
|
||||
if (!terrainPtr->isLoaded()) {
|
||||
LOG_ERROR("Failed to parse ADT terrain: ", adtPath);
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -282,47 +284,47 @@ std::shared_ptr<PendingTile> TerrainManager::prepareTile(int x, int y) {
|
|||
std::to_string(coord.x) + "_" + std::to_string(coord.y) + "_obj0.adt";
|
||||
auto objData = assetManager->readFile(objPath);
|
||||
if (!objData.empty()) {
|
||||
pipeline::ADTTerrain objTerrain = pipeline::ADTLoader::load(objData);
|
||||
if (objTerrain.isLoaded()) {
|
||||
const uint32_t doodadNameBase = static_cast<uint32_t>(terrain.doodadNames.size());
|
||||
const uint32_t wmoNameBase = static_cast<uint32_t>(terrain.wmoNames.size());
|
||||
auto objTerrain = std::make_unique<pipeline::ADTTerrain>(pipeline::ADTLoader::load(objData));
|
||||
if (objTerrain->isLoaded()) {
|
||||
const uint32_t doodadNameBase = static_cast<uint32_t>(terrainPtr->doodadNames.size());
|
||||
const uint32_t wmoNameBase = static_cast<uint32_t>(terrainPtr->wmoNames.size());
|
||||
|
||||
terrain.doodadNames.insert(terrain.doodadNames.end(),
|
||||
objTerrain.doodadNames.begin(), objTerrain.doodadNames.end());
|
||||
terrain.wmoNames.insert(terrain.wmoNames.end(),
|
||||
objTerrain.wmoNames.begin(), objTerrain.wmoNames.end());
|
||||
terrainPtr->doodadNames.insert(terrainPtr->doodadNames.end(),
|
||||
objTerrain->doodadNames.begin(), objTerrain->doodadNames.end());
|
||||
terrainPtr->wmoNames.insert(terrainPtr->wmoNames.end(),
|
||||
objTerrain->wmoNames.begin(), objTerrain->wmoNames.end());
|
||||
|
||||
std::unordered_set<uint32_t> existingDoodadUniqueIds;
|
||||
existingDoodadUniqueIds.reserve(terrain.doodadPlacements.size());
|
||||
for (const auto& p : terrain.doodadPlacements) {
|
||||
existingDoodadUniqueIds.reserve(terrainPtr->doodadPlacements.size());
|
||||
for (const auto& p : terrainPtr->doodadPlacements) {
|
||||
if (p.uniqueId != 0) existingDoodadUniqueIds.insert(p.uniqueId);
|
||||
}
|
||||
|
||||
size_t mergedDoodads = 0;
|
||||
for (auto placement : objTerrain.doodadPlacements) {
|
||||
if (placement.nameId >= objTerrain.doodadNames.size()) continue;
|
||||
for (auto placement : objTerrain->doodadPlacements) {
|
||||
if (placement.nameId >= objTerrain->doodadNames.size()) continue;
|
||||
placement.nameId += doodadNameBase;
|
||||
if (placement.uniqueId != 0 && !existingDoodadUniqueIds.insert(placement.uniqueId).second) {
|
||||
continue;
|
||||
}
|
||||
terrain.doodadPlacements.push_back(placement);
|
||||
terrainPtr->doodadPlacements.push_back(placement);
|
||||
mergedDoodads++;
|
||||
}
|
||||
|
||||
std::unordered_set<uint32_t> existingWmoUniqueIds;
|
||||
existingWmoUniqueIds.reserve(terrain.wmoPlacements.size());
|
||||
for (const auto& p : terrain.wmoPlacements) {
|
||||
existingWmoUniqueIds.reserve(terrainPtr->wmoPlacements.size());
|
||||
for (const auto& p : terrainPtr->wmoPlacements) {
|
||||
if (p.uniqueId != 0) existingWmoUniqueIds.insert(p.uniqueId);
|
||||
}
|
||||
|
||||
size_t mergedWmos = 0;
|
||||
for (auto placement : objTerrain.wmoPlacements) {
|
||||
if (placement.nameId >= objTerrain.wmoNames.size()) continue;
|
||||
for (auto placement : objTerrain->wmoPlacements) {
|
||||
if (placement.nameId >= objTerrain->wmoNames.size()) continue;
|
||||
placement.nameId += wmoNameBase;
|
||||
if (placement.uniqueId != 0 && !existingWmoUniqueIds.insert(placement.uniqueId).second) {
|
||||
continue;
|
||||
}
|
||||
terrain.wmoPlacements.push_back(placement);
|
||||
terrainPtr->wmoPlacements.push_back(placement);
|
||||
mergedWmos++;
|
||||
}
|
||||
|
||||
|
|
@ -334,11 +336,11 @@ std::shared_ptr<PendingTile> TerrainManager::prepareTile(int x, int y) {
|
|||
}
|
||||
|
||||
// Set tile coordinates so mesh knows where to position this tile in world
|
||||
terrain.coord.x = x;
|
||||
terrain.coord.y = y;
|
||||
terrainPtr->coord.x = x;
|
||||
terrainPtr->coord.y = y;
|
||||
|
||||
// Generate mesh
|
||||
pipeline::TerrainMesh mesh = pipeline::TerrainMeshGenerator::generate(terrain);
|
||||
pipeline::TerrainMesh mesh = pipeline::TerrainMeshGenerator::generate(*terrainPtr);
|
||||
if (mesh.validChunkCount == 0) {
|
||||
LOG_ERROR("Failed to generate terrain mesh: ", adtPath);
|
||||
return nullptr;
|
||||
|
|
@ -346,7 +348,7 @@ std::shared_ptr<PendingTile> TerrainManager::prepareTile(int x, int y) {
|
|||
|
||||
auto pending = std::make_shared<PendingTile>();
|
||||
pending->coord = coord;
|
||||
pending->terrain = std::move(terrain);
|
||||
pending->terrain = std::move(*terrainPtr);
|
||||
pending->mesh = std::move(mesh);
|
||||
|
||||
std::unordered_set<uint32_t> preparedModelIds;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue