mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 15:20:15 +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
24
.github/workflows/build.yml
vendored
24
.github/workflows/build.yml
vendored
|
|
@ -55,7 +55,7 @@ jobs:
|
|||
libavutil-dev \
|
||||
libunicorn-dev \
|
||||
libx11-dev
|
||||
sudo apt-get install -y libstormlib-dev || true
|
||||
sudo apt-get install -y libstorm-dev || true
|
||||
|
||||
- name: Configure
|
||||
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||||
|
|
@ -191,9 +191,16 @@ jobs:
|
|||
mingw-w64-clang-aarch64-shaderc
|
||||
git
|
||||
|
||||
- name: Install optional packages
|
||||
- name: Build StormLib from source
|
||||
shell: msys2 {0}
|
||||
run: pacman -S --noconfirm --needed mingw-w64-clang-aarch64-stormlib || true
|
||||
run: |
|
||||
git clone --depth 1 https://github.com/ladislav-zezula/StormLib.git /tmp/StormLib
|
||||
cmake -S /tmp/StormLib -B /tmp/StormLib/build -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="$MINGW_PREFIX" \
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
cmake --build /tmp/StormLib/build --parallel $(nproc)
|
||||
cmake --install /tmp/StormLib/build
|
||||
|
||||
- name: Configure
|
||||
shell: msys2 {0}
|
||||
|
|
@ -254,9 +261,16 @@ jobs:
|
|||
mingw-w64-x86_64-nsis
|
||||
git
|
||||
|
||||
- name: Install optional packages
|
||||
- name: Build StormLib from source
|
||||
shell: msys2 {0}
|
||||
run: pacman -S --noconfirm --needed mingw-w64-x86_64-stormlib || true
|
||||
run: |
|
||||
git clone --depth 1 https://github.com/ladislav-zezula/StormLib.git /tmp/StormLib
|
||||
cmake -S /tmp/StormLib -B /tmp/StormLib/build -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="$MINGW_PREFIX" \
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
cmake --build /tmp/StormLib/build --parallel $(nproc)
|
||||
cmake --install /tmp/StormLib/build
|
||||
|
||||
- name: Configure
|
||||
shell: msys2 {0}
|
||||
|
|
|
|||
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
|
|
@ -54,7 +54,7 @@ jobs:
|
|||
libavutil-dev \
|
||||
libunicorn-dev \
|
||||
libx11-dev
|
||||
sudo apt-get install -y libstormlib-dev || true
|
||||
sudo apt-get install -y libstorm-dev || true
|
||||
|
||||
- name: Configure
|
||||
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||||
|
|
@ -250,9 +250,19 @@ jobs:
|
|||
- name: Install optional packages
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
pacman -S --noconfirm --needed ${{ matrix.prefix }}-stormlib || true
|
||||
pacman -S --noconfirm --needed zip
|
||||
|
||||
- name: Build StormLib from source
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
git clone --depth 1 https://github.com/ladislav-zezula/StormLib.git /tmp/StormLib
|
||||
cmake -S /tmp/StormLib -B /tmp/StormLib/build -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="$MINGW_PREFIX" \
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
cmake --build /tmp/StormLib/build --parallel $(nproc)
|
||||
cmake --install /tmp/StormLib/build
|
||||
|
||||
- name: Configure
|
||||
shell: msys2 {0}
|
||||
run: cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
|
||||
|
|
|
|||
4
.github/workflows/security.yml
vendored
4
.github/workflows/security.yml
vendored
|
|
@ -45,7 +45,7 @@ jobs:
|
|||
libavutil-dev \
|
||||
libunicorn-dev \
|
||||
libx11-dev
|
||||
sudo apt-get install -y libstormlib-dev || true
|
||||
sudo apt-get install -y libstorm-dev || true
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
|
|
@ -117,7 +117,7 @@ jobs:
|
|||
libavutil-dev \
|
||||
libunicorn-dev \
|
||||
libx11-dev
|
||||
sudo apt-get install -y libstormlib-dev || true
|
||||
sudo apt-get install -y libstorm-dev || true
|
||||
|
||||
- name: Configure (ASan/UBSan)
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -29,9 +29,16 @@ $ErrorActionPreference = "Stop"
|
|||
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$BuildDir = Join-Path $ScriptDir "build"
|
||||
$Binary = Join-Path $BuildDir "bin\asset_extract.exe"
|
||||
$OutputDir = Join-Path $ScriptDir "Data"
|
||||
|
||||
# Prefer pre-built binary next to this script (release archives), then build dir
|
||||
$BinaryLocal = Join-Path $ScriptDir "asset_extract.exe"
|
||||
if (Test-Path $BinaryLocal) {
|
||||
$Binary = $BinaryLocal
|
||||
} else {
|
||||
$Binary = Join-Path $BuildDir "bin\asset_extract.exe"
|
||||
}
|
||||
|
||||
# --- Validate arguments ---
|
||||
if (-not (Test-Path $MpqDir -PathType Container)) {
|
||||
Write-Error "Error: Directory not found: $MpqDir"
|
||||
|
|
|
|||
|
|
@ -17,9 +17,15 @@ set -euo pipefail
|
|||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BUILD_DIR="${SCRIPT_DIR}/build"
|
||||
BINARY="${BUILD_DIR}/bin/asset_extract"
|
||||
OUTPUT_DIR="${SCRIPT_DIR}/Data"
|
||||
|
||||
# Prefer pre-built binary next to this script (release archives), then build dir
|
||||
if [ -x "${SCRIPT_DIR}/asset_extract" ]; then
|
||||
BINARY="${SCRIPT_DIR}/asset_extract"
|
||||
else
|
||||
BINARY="${BUILD_DIR}/bin/asset_extract"
|
||||
fi
|
||||
|
||||
# --- Validate arguments ---
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "Usage: $0 /path/to/WoW/Data [classic|turtle|tbc|wotlk]"
|
||||
|
|
@ -73,7 +79,7 @@ if [ ! -f "$BINARY" ]; then
|
|||
fi
|
||||
if [ "$STORMLIB_FOUND" = false ]; then
|
||||
echo "Error: StormLib not found."
|
||||
echo " Ubuntu/Debian: sudo apt install libstormlib-dev"
|
||||
echo " Ubuntu/Debian: sudo apt install libstorm-dev"
|
||||
echo " macOS: brew install stormlib"
|
||||
echo " From source: https://github.com/ladislav-zezula/StormLib"
|
||||
exit 1
|
||||
|
|
|
|||
|
|
@ -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