Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
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

# -------------------------------------------------------------------
# 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
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.

# -------------------------------------------------------------------
# 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

# -------------------------------------------------------------------
# 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
with:
arch: x86
toolset: 14.16 # toolset do VS 2017

# -------------------------------------------------------------------
# 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
run: |
msbuild build_temp\modloader.sln ^
/p:Configuration=${{ matrix.configuration }} ^
/p:Platform=Win32 ^
/p:PlatformToolset=v141_xp ^
/m /v:m

# -------------------------------------------------------------------
# Collect generated binaries.
# Premake output layout: bin/ (modloader.asi) and
# bin/plugins/gta3/*.dll for plugins.
# -------------------------------------------------------------------
- name: Collect artifacts
shell: pwsh
run: |
$cfg = "${{ matrix.configuration }}"
$dest = "artifacts\modloader-$cfg"

# Main ASI binary
New-Item -ItemType Directory -Force -Path "$dest" | Out-Null
Copy-Item "bin\modloader.asi" "$dest\" -ErrorAction SilentlyContinue

# 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
}

# 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

# 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

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

# -----------------------------------------------------------------------
# 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')
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
2 changes: 1 addition & 1 deletion src/core/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/core/extras/gta3/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<void(MenuEntry&)> cb) -> std::function<bool(ActionInfo&)>
{
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)
{
Expand Down
2 changes: 2 additions & 0 deletions src/core/loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<class T>
struct SimplePriorityPred
Expand Down
2 changes: 1 addition & 1 deletion src/core/profiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#ifndef ARGS_TRANSLATOR_STDCALL_HPP
#define ARGS_TRANSLATOR_STDCALL_HPP
#include <intrin.h>


#include "translator_basic.hpp"

Expand Down
34 changes: 19 additions & 15 deletions src/plugins/gta3/std.data/cache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,25 +381,29 @@ class data_cache : public modloader::basic_cache
using stream_type = typename std::conditional<Output, std::ofstream, std::ifstream>::type;
using archive_type = typename std::conditional<Output, cereal::BinaryOutputArchive, cereal::BinaryInputArchive>::type;

stream_type ss;
try {
stream_type ss;

std::unique_ptr<char[]> buffer(new char[buffer_size]);
ss.rdbuf()->pubsetbuf(buffer.get(), buffer_size);
std::unique_ptr<char[]> 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;
}
Expand Down
40 changes: 25 additions & 15 deletions src/plugins/gta3/std.data/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down