@echo off rem Builds the configured game targets and the injector into bin\. setlocal DisableDelayedExpansion set "ROOT=%~dp0" set "OUT=%ROOT%bin" set "OBJ=%ROOT%artifacts\obj\native" set "SRC=%ROOT%src\TerraSharp.Injector" set "NATIVE_ARCH=" if /i "%~1"=="injector" goto native set "GamePathsLoaded=" for /f "usebackq tokens=1,* delims==" %%a in (`powershell -NoProfile -NonInteractive -Command "$ErrorActionPreference = 'Stop'; try { $properties = [xml](Get-Content -LiteralPath ($env:ROOT + 'Directory.Build.props') -Raw); foreach ($name in 'TerrariaDir', 'TModLoaderDir') { $value = $properties.SelectSingleNode('/Project/PropertyGroup/' + $name).InnerText; Write-Output ($name + '=' + $value) }; 'GamePathsLoaded=1' } catch { [Console]::Error.WriteLine($_.Exception.Message); exit 1 }"`) do if not defined %%a set "%%a=%%b" if not defined GamePathsLoaded exit /b 1 if not exist "%TerrariaDir%\Terraria.exe" (echo Terraria not found at the configured path, skipping its build & goto tmodloader) echo Terraria: "%TerrariaDir%" dotnet build "%ROOT%src\TerraSharp\TerraSharp.csproj" -c Release -f net48 -o "%OUT%" "-p:TerrariaDir=%TerrariaDir%" || exit /b 1 :tmodloader if not exist "%TModLoaderDir%\tModLoader.dll" (echo tModLoader not found at the configured path, skipping its build & goto native) echo tModLoader: "%TModLoaderDir%" dotnet build "%ROOT%src\TerraSharp\TerraSharp.csproj" -c Release -f net8.0 -o "%OUT%" "-p:TModLoaderDir=%TModLoaderDir%" || exit /b 1 :native if /i not "%~1"=="injector" if not exist "%TerrariaDir%\Terraria.exe" if not exist "%TModLoaderDir%\tModLoader.dll" (echo Set TerrariaDir or TModLoaderDir in Directory.Build.props to an installed game & exit /b 1) set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" for /f "usebackq delims=" %%i in (`call "%VSWHERE%" -latest -products * -property installationPath`) do set "VS=%%i" if not defined VS (echo Visual Studio not found & exit /b 1) if not exist "%OUT%" mkdir "%OUT%" call :assemble || exit /b 1 call :assembleX64 || exit /b 1 call :embed || exit /b 1 call :compile || exit /b 1 del /q "%OUT%\TerraSharp.Bootstrap.x86.dll" "%OUT%\TerraSharp.Bootstrap.x64.dll" "%OUT%\TerraSharp.tModLoader.runtimeconfig.json" 2>nul echo Built into %OUT% exit /b 0 :assemble call :check "%OBJ%\x86\bootstrap.obj" "%SRC%\bootstrap-x86.asm" if errorlevel 2 exit /b 1 if not errorlevel 1 (echo x86 bootstrap is up to date & exit /b 0) call :setup x86 || exit /b 1 if not exist "%OBJ%\x86" mkdir "%OBJ%\x86" ml /nologo /c /Fo"%OBJ%\x86\bootstrap.obj" "%SRC%\bootstrap-x86.asm" || (del /q "%OBJ%\x86\bootstrap.obj" 2>nul & exit /b 1) exit /b 0 :assembleX64 call :check "%OBJ%\x64\bootstrap.obj" "%SRC%\bootstrap-x64.asm" if errorlevel 2 exit /b 1 if not errorlevel 1 (echo x64 bootstrap is up to date & exit /b 0) call :setup x64 || exit /b 1 if not exist "%OBJ%\x64" mkdir "%OBJ%\x64" ml64 /nologo /c /Fo"%OBJ%\x64\bootstrap.obj" "%SRC%\bootstrap-x64.asm" || (del /q "%OBJ%\x64\bootstrap.obj" 2>nul & exit /b 1) exit /b 0 :embed call :check "%OBJ%\bootstrap.generated.h" "%OBJ%\x86\bootstrap.obj" "%OBJ%\x64\bootstrap.obj" "%SRC%\embed-bootstrap.ps1" if errorlevel 2 exit /b 1 if not errorlevel 1 (echo Embedded bootstrap header is up to date & exit /b 0) powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "%SRC%\embed-bootstrap.ps1" -X86Object "%OBJ%\x86\bootstrap.obj" -X64Object "%OBJ%\x64\bootstrap.obj" -Output "%OBJ%\bootstrap.generated.h" || (del /q "%OBJ%\bootstrap.generated.h" 2>nul & exit /b 1) exit /b 0 :compile call :check "%OUT%\TerraSharp.Injector.exe" "%SRC%\injector.cpp" "%SRC%\bootstrap.h" "%OBJ%\bootstrap.generated.h" if errorlevel 2 exit /b 1 if not errorlevel 1 (echo Injector is up to date & exit /b 0) call :setup x64 || exit /b 1 if not exist "%OBJ%\x64" mkdir "%OBJ%\x64" set "FLAGS=/nologo /W4 /O2 /EHsc /std:c++17 /MT /DUNICODE /D_UNICODE /I"%OBJ%" /Fo"%OBJ%\x64/"" cl %FLAGS% "%SRC%\injector.cpp" /Fe"%OUT%\TerraSharp.Injector.exe" /link mscoree.lib || (del /q "%OUT%\TerraSharp.Injector.exe" 2>nul & exit /b 1) exit /b 0 :check setlocal set "BUILD_CHECK_OUTPUT=%~1" set "BUILD_CHECK_INPUTS=%ROOT%build.bat" shift :checkInput if "%~1"=="" goto checkTimestamps set "BUILD_CHECK_INPUTS=%BUILD_CHECK_INPUTS%|%~1" shift goto checkInput :checkTimestamps rem Exit codes: 0 up to date, 1 rebuild, 2 check failed. powershell -NoProfile -NonInteractive -Command "$ErrorActionPreference = 'Stop'; try { $inputFiles = @($env:BUILD_CHECK_INPUTS.Split('|') | ForEach-Object { Get-Item -LiteralPath $_ }); if (-not (Test-Path -LiteralPath $env:BUILD_CHECK_OUTPUT -PathType Leaf)) { exit 1 }; $outputTime = (Get-Item -LiteralPath $env:BUILD_CHECK_OUTPUT).LastWriteTimeUtc; foreach ($inputFile in $inputFiles) { if ($inputFile.LastWriteTimeUtc -gt $outputTime) { exit 1 } }; exit 0 } catch { [Console]::Error.WriteLine($_.Exception.Message); exit 2 }" endlocal & exit /b %errorlevel% :setup if "%NATIVE_ARCH%"=="%~1" exit /b 0 call "%VS%\VC\Auxiliary\Build\vcvarsall.bat" %~1 >nul 2>&1 || exit /b 1 set "NATIVE_ARCH=%~1" exit /b 0