From 8f3be051469bec81b4d83e91d4c53f577af4c88c Mon Sep 17 00:00:00 2001 From: Fabio Rossini Sluzala Date: Mon, 13 Apr 2026 13:22:40 -0300 Subject: [PATCH 1/6] feat(menu.cpp, loader.hpp, profiles.cpp): introduce priority_limit and use it to clamp priority values, allowing for more flexible configuration --- src/core/extras/gta3/menu.cpp | 2 +- src/core/loader.hpp | 2 ++ src/core/profiles.cpp | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/extras/gta3/menu.cpp b/src/core/extras/gta3/menu.cpp index 186ed6c8..7f42be49 100644 --- a/src/core/extras/gta3/menu.cpp +++ b/src/core/extras/gta3/menu.cpp @@ -610,7 +610,7 @@ void TheMenu::ModPageEvents() // Helper function to setup a integer priority entry in the menu auto SetupPriorityEntry = [this](const char* label, uint32_t& priority, std::function cb) -> std::function { - static const uint32_t min = 0, max = 100, step = 1; + static const uint32_t min = 0, max = priority_limit, step = 1; auto PriorityLabel = [](const uint32_t& priority) { diff --git a/src/core/loader.hpp b/src/core/loader.hpp index 2728ad39..8160dd62 100644 --- a/src/core/loader.hpp +++ b/src/core/loader.hpp @@ -34,6 +34,8 @@ static const char* downurl = "https://github.com/thelink2012/modloader/releases" // static const char* default_profile_name = "Default"; +static const int priority_limit = 9999; + // Functor for sorting based on priority template struct SimplePriorityPred diff --git a/src/core/profiles.cpp b/src/core/profiles.cpp index 94915281..dda4b729 100644 --- a/src/core/profiles.cpp +++ b/src/core/profiles.cpp @@ -256,7 +256,7 @@ void Loader::Profile::SetPriority(std::string name, int priority) if(priority == default_priority) mods_priority.erase(name); else - mods_priority[name] = std::max(std::min(priority, 100), 0); // clamp to 0-100 + mods_priority[name] = std::max(std::min(priority, priority_limit), 0); // clamp to 0-priority_limit } /* From 0bf80cff72e3a4e2176fa68af71ee869a1c4a623 Mon Sep 17 00:00:00 2001 From: Fabio Rossini Sluzala Date: Mon, 13 Apr 2026 13:25:03 -0300 Subject: [PATCH 2/6] fix(config.cpp): update priority calculation to use a variable limit instead of hardcoded 100 --- src/core/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/config.cpp b/src/core/config.cpp index dd953f38..37d4731b 100644 --- a/src/core/config.cpp +++ b/src/core/config.cpp @@ -242,7 +242,7 @@ void Loader::UpdateOldConfig_0115_021() for(auto& kv : newer["Priority"]) { auto pr = std::stoi(kv.second); - kv.second = std::to_string(pr > 0 && pr <= 100? 101 - pr : pr); + kv.second = std::to_string(pr > 0 && pr <= priority_limit? (priority_limit + 1) - pr : pr); } newer.write_file(gamePath + "modloader/" + folderConfigFilename); From 19c65160ccf11ca33ccaf7841bcbc068652da71b Mon Sep 17 00:00:00 2001 From: Fabio Rossini Sluzala Date: Mon, 13 Apr 2026 13:25:36 -0300 Subject: [PATCH 3/6] feat(translator_stdcall.hpp): include for intrinsic functions support --- src/plugins/gta3/std.asi/args_translator/translator_stdcall.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/gta3/std.asi/args_translator/translator_stdcall.hpp b/src/plugins/gta3/std.asi/args_translator/translator_stdcall.hpp index 5e897635..5a8c384c 100644 --- a/src/plugins/gta3/std.asi/args_translator/translator_stdcall.hpp +++ b/src/plugins/gta3/std.asi/args_translator/translator_stdcall.hpp @@ -9,6 +9,8 @@ #ifndef ARGS_TRANSLATOR_STDCALL_HPP #define ARGS_TRANSLATOR_STDCALL_HPP +#include + #include "translator_basic.hpp" From 7c80380e25b50834182f263715fe9087246409da Mon Sep 17 00:00:00 2001 From: Fabio Rossini Sluzala Date: Mon, 13 Apr 2026 13:39:15 -0300 Subject: [PATCH 4/6] ci: add GitHub Actions workflow for building and releasing the project --- .github/workflows/build.yml | 149 ++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..f9026b8b --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,149 @@ +name: Build + +on: + push: + branches: ["**"] + tags: ["v*.*.*"] + pull_request: + workflow_dispatch: + +jobs: + build: + runs-on: windows-2022 + + strategy: + fail-fast: false + matrix: + configuration: [Release, Debug] + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + # ------------------------------------------------------------------- + # Instala o toolset v141 (VS 2017) + suporte a XP no VS 2022 presente + # no runner. O componente WinXP habilita o v141_xp usado pelo premake. + # ------------------------------------------------------------------- + - name: Install v141_xp toolset + shell: cmd + run: | + "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\setup.exe" modify ^ + --passive --norestart ^ + --installPath "C:\Program Files\Microsoft Visual Studio\2022\Enterprise" ^ + --add Microsoft.VisualStudio.Component.VC.v141.x86.x64 ^ + --add Microsoft.VisualStudio.Component.WinXP + # Timeout ocasional é esperado; o step falha limpo se o installer + # retornar código != 0, o que torna o problema visível nos logs. + + # ------------------------------------------------------------------- + # Gera os projetos VS2015 via Premake (o .exe já está no repo). + # O premake define PlatformToolset=v140_xp nos .vcxproj; vamos + # sobrescrever isso no MSBuild mais abaixo — sem tocar no premake5.lua. + # ------------------------------------------------------------------- + - name: Generate project files (vs2015) + shell: cmd + run: premake5.exe vs2015 --outdir=build_temp + + # ------------------------------------------------------------------- + # Configura o ambiente MSVC para o toolset 14.16 (VS 2017 / v141). + # Necessário para que o msbuild encontre o compilador correto. + # ------------------------------------------------------------------- + - name: Setup MSVC environment (v141) + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x86 + toolset: 14.16 # toolset do VS 2017 + + # ------------------------------------------------------------------- + # Compila sobrescrevendo o PlatformToolset para v141_xp. + # + # Por que funciona sem mexer nos .vcxproj: + # O MSBuild permite que qualquer propriedade definida em /p: na linha + # de comando tenha precedência sobre o valor do arquivo de projeto. + # "v141_xp" é exatamente o mesmo toolset que você confirmou funcionar + # ao alterar manualmente pelo Visual Studio 2017. + # + # /m → paralelismo (usa todos os núcleos do runner). + # /v:m → verbosidade minimal para logs legíveis. + # ------------------------------------------------------------------- + - name: Build (${{ matrix.configuration }}) + shell: cmd + run: | + msbuild build_temp\modloader.sln ^ + /p:Configuration=${{ matrix.configuration }} ^ + /p:Platform=Win32 ^ + /p:PlatformToolset=v141_xp ^ + /m /v:m + + # ------------------------------------------------------------------- + # Coleta os binários gerados. + # Estrutura de saída do premake: bin/ (modloader.asi) e + # bin/plugins/gta3/*.dll para os plugins. + # ------------------------------------------------------------------- + - name: Collect artifacts + shell: pwsh + run: | + $cfg = "${{ matrix.configuration }}" + $dest = "artifacts\modloader-$cfg" + + # ASI principal + New-Item -ItemType Directory -Force -Path "$dest" | Out-Null + Copy-Item "bin\modloader.asi" "$dest\" -ErrorAction SilentlyContinue + + # Plugins gta3 + $pluginSrc = "bin\plugins\gta3" + if (Test-Path $pluginSrc) { + New-Item -ItemType Directory -Force -Path "$dest\plugins\gta3" | Out-Null + Copy-Item "$pluginSrc\*.dll" "$dest\plugins\gta3\" -ErrorAction SilentlyContinue + } + + # PDBs (ficam junto aos binários no mesmo diretório) + Copy-Item "bin\*.pdb" "$dest\" -ErrorAction SilentlyContinue + Copy-Item "bin\plugins\gta3\*.pdb" "$dest\plugins\gta3\" -ErrorAction SilentlyContinue + + # Docs / configs de exemplo + Copy-Item "doc\config\*.ini.0" "$dest\" -ErrorAction SilentlyContinue + Copy-Item "doc\CHANGELOG.md" "$dest\" -ErrorAction SilentlyContinue + Copy-Item "LICENSE" "$dest\" -ErrorAction SilentlyContinue + + Write-Host "=== Artifacts ===" + Get-ChildItem -Recurse $dest | Select-Object FullName + + - name: Upload artifact – ${{ matrix.configuration }} + uses: actions/upload-artifact@v4 + with: + name: modloader-${{ matrix.configuration }}-${{ github.sha }} + path: artifacts\modloader-${{ matrix.configuration }}\ + if-no-files-found: error + retention-days: 30 + + # ----------------------------------------------------------------------- + # Job extra: cria uma Release no GitHub quando uma tag "v*.*.*" é enviada. + # Só roda se o job build (Release) passou. + # ----------------------------------------------------------------------- + release: + if: startsWith(github.ref, 'refs/tags/v') + needs: build + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Download Release artifact + uses: actions/download-artifact@v4 + with: + name: modloader-Release-${{ github.sha }} + path: dist/ + + - name: Zip release + run: | + cd dist + zip -r ../modloader-${{ github.ref_name }}.zip . + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + files: modloader-${{ github.ref_name }}.zip + generate_release_notes: true From 0e092d9fcb89ebe7cbcfc19ace96cce07a78e4a5 Mon Sep 17 00:00:00 2001 From: Fabio Rossini Sluzala Date: Wed, 15 Apr 2026 00:13:22 -0300 Subject: [PATCH 5/6] fix(cache.hpp, main.cpp): add try-catch blocks to handle exceptions during cache operations feat(cache.hpp, main.cpp): log error messages with exception details when cache operations fail --- src/plugins/gta3/std.data/cache.hpp | 34 +++++++++++++----------- src/plugins/gta3/std.data/main.cpp | 40 ++++++++++++++++++----------- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/plugins/gta3/std.data/cache.hpp b/src/plugins/gta3/std.data/cache.hpp index deef90f8..23f82a09 100644 --- a/src/plugins/gta3/std.data/cache.hpp +++ b/src/plugins/gta3/std.data/cache.hpp @@ -381,25 +381,29 @@ class data_cache : public modloader::basic_cache using stream_type = typename std::conditional::type; using archive_type = typename std::conditional::type; - stream_type ss; + try { + stream_type ss; - std::unique_ptr buffer(new char[buffer_size]); - ss.rdbuf()->pubsetbuf(buffer.get(), buffer_size); + std::unique_ptr buffer(new char[buffer_size]); + ss.rdbuf()->pubsetbuf(buffer.get(), buffer_size); - ss.open(filepath, std::ios::binary); - if(ss.is_open()) - { - uint32_t version = build_identifier(); // This variable won't change in the case of a output stream, - // but will in the case of a input stream, in any case default initialize for the output case - archive_type archive(ss); - archive(version); - if(version == build_identifier()) // Make sure serialization version matches + ss.open(filepath, std::ios::binary); + if(ss.is_open()) { - func(ss, archive); - return true; + uint32_t version = build_identifier(); // This variable won't change in the case of a output stream, + // but will in the case of a input stream, in any case default initialize for the output case + archive_type archive(ss); + archive(version); + if(version == build_identifier()) // Make sure serialization version matches + { + func(ss, archive); + return true; + } + else + plugin_ptr->Log("Warning: Incompatible cache version, a new cache will be generated."); } - else - plugin_ptr->Log("Warning: Incompatible cache version, a new cache will be generated."); + } catch (const std::exception &e) { + plugin_ptr->Log("Error: Failed to perform cache operation: %s on %s", e.what(), filepath.c_str()); } return false; } diff --git a/src/plugins/gta3/std.data/main.cpp b/src/plugins/gta3/std.data/main.cpp index 69985228..38022f62 100644 --- a/src/plugins/gta3/std.data/main.cpp +++ b/src/plugins/gta3/std.data/main.cpp @@ -638,15 +638,20 @@ auto DataPlugin::ReadCachedReadmeListing() -> readme_listing_type { readme_listing_type cached_readme_listing; - std::ifstream ss(cache.GetCachePath("readme.ld"), std::ios::binary); - if(ss.is_open()) - { - cereal::BinaryInputArchive archive(ss); - if(VerifyCachedReadme(ss, archive)) + try { + std::ifstream ss(cache.GetCachePath("readme.ld"), std::ios::binary); + if(ss.is_open()) { - block_reader listing_block(ss); - archive(cached_readme_listing); + cereal::BinaryInputArchive archive(ss); + if(VerifyCachedReadme(ss, archive)) + { + block_reader listing_block(ss); + archive(cached_readme_listing); + } } + } catch(const std::exception& e) { + this->Log("Error: Failed to read cached readme listing: {}", e.what()); + cached_readme_listing.clear(); } return cached_readme_listing; } @@ -659,16 +664,21 @@ auto DataPlugin::ReadCachedReadmeStore() -> readme_data_store { readme_data_store store_lines; - std::ifstream ss(cache.GetCachePath("readme.ld"), std::ios::binary); - if(ss.is_open()) - { - cereal::BinaryInputArchive archive(ss); - if(VerifyCachedReadme(ss, archive)) + try { + std::ifstream ss(cache.GetCachePath("readme.ld"), std::ios::binary); + if(ss.is_open()) { - block_reader::skip(ss); // skip listing block - block_reader lines_block(ss); - archive(store_lines); + cereal::BinaryInputArchive archive(ss); + if(VerifyCachedReadme(ss, archive)) + { + block_reader::skip(ss); // skip listing block + block_reader lines_block(ss); + archive(store_lines); + } } + } catch(const std::exception& e) { + this->Log("Error: Failed to read cached readme store: {}", e.what()); + store_lines.clear(); } return store_lines; } From b4ae3a8fc3b199c4dd876950192ec7afb0776647 Mon Sep 17 00:00:00 2001 From: Fabio Rossini Sluzala Date: Mon, 20 Apr 2026 13:06:11 -0300 Subject: [PATCH 6/6] ci(build.yml): update comments for clarity and consistency ci(build.yml): add detailed comments explaining each step in the build process ci(build.yml): correct comment about MSBuild property precedence and toolset version ci(build.yml): update artifact collection comments to reflect current directory structure ci(build.yml): add comments explaining the purpose of the release job --- .github/workflows/build.yml | 49 +++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f9026b8b..79d66374 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,8 +23,8 @@ jobs: submodules: recursive # ------------------------------------------------------------------- - # Instala o toolset v141 (VS 2017) + suporte a XP no VS 2022 presente - # no runner. O componente WinXP habilita o v141_xp usado pelo premake. + # Install v141 (VS 2017) toolset and WinXP support on the runner. + # The WinXP component provides the v141_xp toolset required by premake. # ------------------------------------------------------------------- - name: Install v141_xp toolset shell: cmd @@ -38,17 +38,18 @@ jobs: # retornar código != 0, o que torna o problema visível nos logs. # ------------------------------------------------------------------- - # Gera os projetos VS2015 via Premake (o .exe já está no repo). - # O premake define PlatformToolset=v140_xp nos .vcxproj; vamos - # sobrescrever isso no MSBuild mais abaixo — sem tocar no premake5.lua. + # Generate VS2015 project files using Premake (premake5.exe included + # in the repository). + # Premake sets PlatformToolset=v140_xp in the .vcxproj files; this is + # overridden when invoking MSBuild below without modifying premake5.lua. # ------------------------------------------------------------------- - name: Generate project files (vs2015) shell: cmd run: premake5.exe vs2015 --outdir=build_temp # ------------------------------------------------------------------- - # Configura o ambiente MSVC para o toolset 14.16 (VS 2017 / v141). - # Necessário para que o msbuild encontre o compilador correto. + # Configure MSVC environment for toolset 14.16 (VS 2017 / v141). + # Required so msbuild can locate the correct compiler and toolset. # ------------------------------------------------------------------- - name: Setup MSVC environment (v141) uses: ilammy/msvc-dev-cmd@v1 @@ -57,16 +58,12 @@ jobs: toolset: 14.16 # toolset do VS 2017 # ------------------------------------------------------------------- - # Compila sobrescrevendo o PlatformToolset para v141_xp. - # - # Por que funciona sem mexer nos .vcxproj: - # O MSBuild permite que qualquer propriedade definida em /p: na linha - # de comando tenha precedência sobre o valor do arquivo de projeto. - # "v141_xp" é exatamente o mesmo toolset que você confirmou funcionar - # ao alterar manualmente pelo Visual Studio 2017. - # - # /m → paralelismo (usa todos os núcleos do runner). - # /v:m → verbosidade minimal para logs legíveis. + # Build and override PlatformToolset to v141_xp via MSBuild. + # MSBuild command-line properties passed with /p: take precedence over + # project file values. v141_xp is the v141 toolset variant that provides + # WinXP support. + # /m -> enable parallel build using all available cores. + # /v:m -> minimal verbosity for concise logs. # ------------------------------------------------------------------- - name: Build (${{ matrix.configuration }}) shell: cmd @@ -78,9 +75,9 @@ jobs: /m /v:m # ------------------------------------------------------------------- - # Coleta os binários gerados. - # Estrutura de saída do premake: bin/ (modloader.asi) e - # bin/plugins/gta3/*.dll para os plugins. + # Collect generated binaries. + # Premake output layout: bin/ (modloader.asi) and + # bin/plugins/gta3/*.dll for plugins. # ------------------------------------------------------------------- - name: Collect artifacts shell: pwsh @@ -88,22 +85,22 @@ jobs: $cfg = "${{ matrix.configuration }}" $dest = "artifacts\modloader-$cfg" - # ASI principal + # Main ASI binary New-Item -ItemType Directory -Force -Path "$dest" | Out-Null Copy-Item "bin\modloader.asi" "$dest\" -ErrorAction SilentlyContinue - # Plugins gta3 + # GTA3 plugins $pluginSrc = "bin\plugins\gta3" if (Test-Path $pluginSrc) { New-Item -ItemType Directory -Force -Path "$dest\plugins\gta3" | Out-Null Copy-Item "$pluginSrc\*.dll" "$dest\plugins\gta3\" -ErrorAction SilentlyContinue } - # PDBs (ficam junto aos binários no mesmo diretório) + # PDB files (placed with binaries in the same directory) Copy-Item "bin\*.pdb" "$dest\" -ErrorAction SilentlyContinue Copy-Item "bin\plugins\gta3\*.pdb" "$dest\plugins\gta3\" -ErrorAction SilentlyContinue - # Docs / configs de exemplo + # Example docs and configuration files Copy-Item "doc\config\*.ini.0" "$dest\" -ErrorAction SilentlyContinue Copy-Item "doc\CHANGELOG.md" "$dest\" -ErrorAction SilentlyContinue Copy-Item "LICENSE" "$dest\" -ErrorAction SilentlyContinue @@ -120,8 +117,8 @@ jobs: retention-days: 30 # ----------------------------------------------------------------------- - # Job extra: cria uma Release no GitHub quando uma tag "v*.*.*" é enviada. - # Só roda se o job build (Release) passou. + # Extra job: create a GitHub Release when a tag matching v*.*.* is pushed. + # Runs only if the build (Release) job completed successfully. # ----------------------------------------------------------------------- release: if: startsWith(github.ref, 'refs/tags/v')