diff --git a/BuildPublish.bat b/BuildPublish.bat
new file mode 100644
index 00000000..7add92c8
--- /dev/null
+++ b/BuildPublish.bat
@@ -0,0 +1,29 @@
+@echo off
+REM Launcher for Cirno No Reason Build and Publish Script
+
+REM Find godot.exe in PATH and set full path
+echo Searching for godot.exe in PATH...
+for /f "delims=" %%i in ('where godot.exe 2^>nul') do set "GODOT=%%i" & goto :found
+
+echo ERROR: godot.exe not found in PATH!
+echo Please ensure Godot is installed and in your PATH, or set GODOT environment variable.
+pause
+exit /b 1
+
+:found
+echo Using GODOT=%GODOT%
+echo Godot executable found.
+echo.
+
+REM Launch PowerShell and keep the window open (-NoExit) so output stays visible
+powershell.exe -NoExit -ExecutionPolicy Bypass -File "%~dp0BuildPublish.ps1"
+
+if %ERRORLEVEL% NEQ 0 (
+ echo.
+ echo Script execution failed with error code %ERRORLEVEL%
+ pause
+) else (
+ echo.
+ echo Script completed successfully. Press any key to close this window.
+ pause >nul
+)
diff --git a/BuildPublish.ps1 b/BuildPublish.ps1
new file mode 100644
index 00000000..d76dd979
--- /dev/null
+++ b/BuildPublish.ps1
@@ -0,0 +1,186 @@
+# Build and Publish Script for Cirno No Reason
+# Interactive launcher with proper Godot export handling
+
+param(
+ [string]$Operation
+)
+
+# Import the module
+$modulePath = Join-Path $PSScriptRoot "CirnoBuild.psm1"
+Import-Module $modulePath -Force
+
+# Configuration
+$script:godotPath = $env:GODOT
+$script:butlerPath = "F:\Apps\butler\butler.exe"
+$script:buildDir = ".\build"
+$script:releaseDir = ".\release"
+$script:platforms = Get-PlatformConfigurations
+
+function Show-Menu {
+ Clear-Host
+ Write-Host "=====================================" -ForegroundColor Cyan
+ Write-Host " Cirno No Reason - Build & Publish" -ForegroundColor Cyan
+ Write-Host "=====================================" -ForegroundColor Cyan
+ Write-Host ""
+ Write-Host "1. Build Windows" -ForegroundColor Green
+ Write-Host "2. Build Linux" -ForegroundColor Green
+ Write-Host "3. Build Windows + Linux" -ForegroundColor Green
+ Write-Host "4. Publish Windows" -ForegroundColor Yellow
+ Write-Host "5. Publish Linux" -ForegroundColor Yellow
+ Write-Host "6. Publish Windows + Linux" -ForegroundColor Yellow
+ Write-Host "7. Build and Publish Windows + Linux" -ForegroundColor Magenta
+ Write-Host "0. Exit" -ForegroundColor Red
+ Write-Host ""
+}
+
+
+function Build-Platforms {
+ param([string[]]$PlatformsToBuild)
+
+ Write-Host ""
+ Write-Host "========================================" -ForegroundColor Cyan
+ Write-Host " Starting Build Process" -ForegroundColor Cyan
+ Write-Host "========================================" -ForegroundColor Cyan
+
+ $prereqResult = Test-Prerequisites -GodotPath $script:godotPath -ButlerPath $script:butlerPath -SkipButler
+ if (-not $prereqResult.Valid) {
+ return @{}
+ }
+
+ # Use resolved path if available
+ if ($prereqResult.ResolvedGodotPath) {
+ $script:godotPath = $prereqResult.ResolvedGodotPath
+ }
+
+ $versionInfo = Get-VersionInfo
+ Initialize-BuildDirectories -PlatformsToBuild $PlatformsToBuild -BuildDir $script:buildDir
+ Update-ExportConfig -VersionInfo $versionInfo
+
+ $results = @{}
+ foreach ($platform in $PlatformsToBuild) {
+ $results[$platform] = Export-GodotPlatform -Platform $platform `
+ -GodotPath $script:godotPath `
+ -BuildDir $script:buildDir `
+ -VersionInfo $versionInfo
+ }
+
+ Write-Host ""
+ Write-Host "Build Summary:" -ForegroundColor Cyan
+ foreach ($platform in $PlatformsToBuild) {
+ $status = if ($results[$platform]) { "SUCCESS" } else { "FAILED" }
+ $color = if ($results[$platform]) { "Green" } else { "Red" }
+ Write-Host " $platform : $status" -ForegroundColor $color
+ }
+
+ return $results
+}
+
+function Publish-Platforms {
+ param([string[]]$PlatformsToPublish)
+
+ Write-Host ""
+ Write-Host "========================================" -ForegroundColor Cyan
+ Write-Host " Starting Publish Process" -ForegroundColor Cyan
+ Write-Host "========================================" -ForegroundColor Cyan
+
+ $prereqResult = Test-Prerequisites -GodotPath $script:godotPath -ButlerPath $script:butlerPath
+ if (-not $prereqResult.Valid) {
+ return @{}
+ }
+
+ # Use resolved path if available
+ if ($prereqResult.ResolvedGodotPath) {
+ $script:godotPath = $prereqResult.ResolvedGodotPath
+ }
+
+ $versionInfo = Get-VersionInfo
+
+ $results = @{}
+ foreach ($platform in $PlatformsToPublish) {
+ $results[$platform] = Publish-PlatformBuild -Platform $platform `
+ -VersionInfo $versionInfo `
+ -BuildDir $script:buildDir `
+ -ReleaseDir $script:releaseDir `
+ -ButlerPath $script:butlerPath
+ }
+
+ Write-Host ""
+ Write-Host "Publish Summary:" -ForegroundColor Cyan
+ foreach ($platform in $PlatformsToPublish) {
+ $status = if ($results[$platform]) { "SUCCESS" } else { "FAILED" }
+ $color = if ($results[$platform]) { "Green" } else { "Red" }
+ Write-Host " $platform : $status" -ForegroundColor $color
+ }
+
+ return $results
+}
+
+function Invoke-Operation {
+ param([string]$Choice)
+
+ switch ($Choice) {
+ "1" {
+ Build-Platforms -PlatformsToBuild @("win")
+ }
+ "2" {
+ Build-Platforms -PlatformsToBuild @("linux")
+ }
+ "3" {
+ Build-Platforms -PlatformsToBuild @("win", "linux")
+ }
+ "4" {
+ Publish-Platforms -PlatformsToPublish @("win")
+ }
+ "5" {
+ Publish-Platforms -PlatformsToPublish @("linux")
+ }
+ "6" {
+ Publish-Platforms -PlatformsToPublish @("win", "linux")
+ }
+ "7" {
+ $buildResults = Build-Platforms -PlatformsToBuild @("win", "linux")
+
+ $platformsToPublish = @()
+ foreach ($platform in @("win", "linux")) {
+ if ($buildResults[$platform]) {
+ $platformsToPublish += $platform
+ }
+ }
+
+ if ($platformsToPublish.Count -gt 0) {
+ Publish-Platforms -PlatformsToPublish $platformsToPublish
+ } else {
+ Write-Host ""
+ Write-Host "ERROR: No successful builds to publish!" -ForegroundColor Red
+ }
+ }
+ "0" {
+ Write-Host "Exiting..." -ForegroundColor Yellow
+ exit 0
+ }
+ default {
+ Write-Host "Invalid selection!" -ForegroundColor Red
+ }
+ }
+}
+
+# Main execution
+if ($Operation) {
+ Invoke-Operation -Choice $Operation
+} else {
+ while ($true) {
+ Show-Menu
+ $choice = Read-Host "Select an option (0-7)"
+
+ if ($choice -eq "0") {
+ Write-Host "Exiting..." -ForegroundColor Yellow
+ break
+ }
+
+ Invoke-Operation -Choice $choice
+
+ Write-Host ""
+ Write-Host "Press any key to continue..." -ForegroundColor Yellow
+ $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
+ }
+}
diff --git a/Cirno.csproj b/Cirno.csproj
index 77a0e240..7d632e26 100644
--- a/Cirno.csproj
+++ b/Cirno.csproj
@@ -15,10 +15,15 @@
GODOT;GODOT_WINDOWS;GODOT_PC;GODOT4;GODOT4_5;GODOT4_5_0;GODOT4_OR_GREATER;GODOT4_0_OR_GREATER;GODOT4_1_OR_GREATER;GODOT4_2_OR_GREATER;GODOT4_3_OR_GREATER;GODOT4_4_OR_GREATER;GODOT4_5_OR_GREATER;GODOT4_5_0_OR_GREATER;TRACE;TOOLS
-
+
+
+
+
+
+
diff --git a/CirnoBuild.psm1 b/CirnoBuild.psm1
new file mode 100644
index 00000000..6cb98382
--- /dev/null
+++ b/CirnoBuild.psm1
@@ -0,0 +1,397 @@
+# CirnoBuild.psm1
+# Common functions for building and publishing Cirno No Reason
+
+# Configuration
+$script:gitVersionPath = "dotnet-gitversion.exe"
+$script:configFile = "export_presets.cfg"
+$script:fileName = "Cirno_No_Reason"
+
+# Platform configurations
+$script:platforms = @{
+ "win" = @{
+ ExportName = "Windows Desktop"
+ Extension = ".exe"
+ OutputSubDir = "win"
+ }
+ "linux" = @{
+ ExportName = "Linux"
+ Extension = ".x86_64"
+ OutputSubDir = "linux"
+ }
+}
+
+function Test-Prerequisites {
+ <#
+ .SYNOPSIS
+ Validates that required tools are available
+
+ .PARAMETER GodotPath
+ Path to Godot executable
+
+ .PARAMETER SkipButler
+ Skip Butler validation (not needed for build-only operations)
+ #>
+ param(
+ [string]$GodotPath,
+ [string]$ButlerPath,
+ [switch]$SkipButler
+ )
+
+ $errors = @()
+
+ if ([string]::IsNullOrWhiteSpace($GodotPath)) {
+ $errors += "GODOT environment variable is not set. Please set it to your Godot executable path."
+ $errors += "Example: `$env:GODOT = 'C:\Godot\Godot_v4.x.exe'"
+ } elseif (-not (Test-Path $GodotPath)) {
+ # Try to resolve from PATH if it's just an executable name
+ $resolvedPath = Get-Command $GodotPath -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Source
+ if ($resolvedPath) {
+ Write-Host " Resolved Godot path: $resolvedPath" -ForegroundColor Gray
+ # Update the caller's variable
+ return @{
+ Valid = $true
+ ResolvedGodotPath = $resolvedPath
+ }
+ } else {
+ $errors += "Godot executable not found at: $GodotPath"
+ $errors += "Please update the GODOT environment variable or add Godot to PATH."
+ }
+ }
+
+ if (-not (Test-Path $script:gitVersionPath) -and -not (Get-Command $script:gitVersionPath -ErrorAction SilentlyContinue)) {
+ $errors += "GitVersion not found. Please install dotnet-gitversion or add it to PATH."
+ }
+
+ if (-not $SkipButler) {
+ if ([string]::IsNullOrWhiteSpace($ButlerPath)) {
+ $errors += "Butler path is not configured."
+ } elseif (-not (Test-Path $ButlerPath)) {
+ $errors += "Butler executable not found at: $ButlerPath"
+ }
+ }
+
+ if ($errors.Count -gt 0) {
+ Write-Host ""
+ Write-Host "ERROR: Missing Prerequisites" -ForegroundColor Red
+ Write-Host "=====================================" -ForegroundColor Red
+ foreach ($error in $errors) {
+ Write-Host " $error" -ForegroundColor Yellow
+ }
+ Write-Host ""
+ return @{
+ Valid = $false
+ }
+ }
+
+ return @{
+ Valid = $true
+ ResolvedGodotPath = $GodotPath
+ }
+}
+
+function Get-VersionInfo {
+ <#
+ .SYNOPSIS
+ Gets version information from GitVersion
+ #>
+ Write-Host "Getting version information..." -ForegroundColor Cyan
+ $gitVersionOutput = & $script:gitVersionPath | ConvertFrom-Json
+
+ $versionInfo = @{
+ AssemblySemFileVer = $gitVersionOutput.AssemblySemFileVer
+ AssemblySemVer = $gitVersionOutput.AssemblySemVer
+ FullSemVer = $gitVersionOutput.FullSemVer
+ PreReleaseLabel = $gitVersionOutput.PreReleaseLabelWithDash
+ }
+
+ [System.Environment]::SetEnvironmentVariable("GIT_ASSEMBLY_SEM_FILE_VER", $versionInfo.AssemblySemFileVer, [System.EnvironmentVariableTarget]::Process)
+ [System.Environment]::SetEnvironmentVariable("GIT_ASSEMBLY_SEM_VER", $versionInfo.AssemblySemVer, [System.EnvironmentVariableTarget]::Process)
+
+ Write-Host " Version: $($versionInfo.FullSemVer)" -ForegroundColor Green
+ Write-Host " File Version: $($versionInfo.AssemblySemFileVer)" -ForegroundColor Green
+
+ return $versionInfo
+}
+
+function Initialize-BuildDirectories {
+ <#
+ .SYNOPSIS
+ Creates and clears build directories for specified platforms
+ #>
+ param(
+ [string[]]$PlatformsToBuild,
+ [string]$BuildDir
+ )
+
+ Write-Host "Initializing build directories..." -ForegroundColor Cyan
+
+ if (Test-Path $BuildDir) {
+ Remove-Item "$BuildDir\*" -Recurse -Force -ErrorAction SilentlyContinue
+ } else {
+ New-Item -ItemType Directory -Path $BuildDir | Out-Null
+ }
+
+ foreach ($platform in $PlatformsToBuild) {
+ $platformDir = Join-Path $BuildDir $script:platforms[$platform].OutputSubDir
+ New-Item -ItemType Directory -Path $platformDir -Force | Out-Null
+ Write-Host " Created: $platformDir" -ForegroundColor Gray
+ }
+}
+
+function Update-ExportConfig {
+ <#
+ .SYNOPSIS
+ Updates export_presets.cfg with version information
+ #>
+ param($VersionInfo)
+
+ Write-Host "Updating export configuration..." -ForegroundColor Cyan
+
+ if (Test-Path $script:configFile) {
+ (Get-Content $script:configFile) `
+ -replace 'application/file_version="[^"]*"', "application/file_version=`"$($VersionInfo.AssemblySemFileVer)`"" `
+ -replace 'application/product_version="[^"]*"', "application/product_version=`"$($VersionInfo.AssemblySemVer)`"" `
+ | Set-Content $script:configFile
+ Write-Host " Export config updated successfully" -ForegroundColor Green
+ } else {
+ Write-Host " WARNING: $script:configFile not found!" -ForegroundColor Red
+ }
+}
+
+function Wait-ForExportCompletion {
+ <#
+ .SYNOPSIS
+ Monitors export output file until it's complete
+ #>
+ param(
+ [string]$OutputPath,
+ [int]$TimeoutSeconds = 300
+ )
+
+ $startTime = Get-Date
+ $checkInterval = 2
+ $lastSize = -1
+ $stableCount = 0
+ $requiredStableChecks = 3
+
+ Write-Host " Waiting for export to complete: $OutputPath" -ForegroundColor Gray
+
+ while (((Get-Date) - $startTime).TotalSeconds -lt $TimeoutSeconds) {
+ Start-Sleep -Seconds $checkInterval
+
+ if (Test-Path $OutputPath) {
+ $currentSize = (Get-Item $OutputPath).Length
+
+ if ($currentSize -eq $lastSize -and $currentSize -gt 0) {
+ $stableCount++
+ if ($stableCount -ge $requiredStableChecks) {
+ Write-Host " Export completed: $OutputPath ($currentSize bytes)" -ForegroundColor Green
+ return $true
+ }
+ } else {
+ $stableCount = 0
+ }
+
+ $lastSize = $currentSize
+ }
+ }
+
+ Write-Host " WARNING: Export timeout reached for $OutputPath" -ForegroundColor Yellow
+ return (Test-Path $OutputPath)
+}
+
+function Create-PlatformZip {
+ <#
+ .SYNOPSIS
+ Creates a zip archive for a platform build
+
+ .PARAMETER Platform
+ Platform identifier (win, linux)
+
+ .PARAMETER BuildDir
+ Build directory path
+
+ .PARAMETER VersionInfo
+ Optional version information hashtable (if provided, includes version in filename)
+
+ .PARAMETER Force
+ Force recreate zip even if it exists
+
+ .RETURNS
+ Path to the created zip file, or $null if failed
+ #>
+ param(
+ [string]$Platform,
+ [string]$BuildDir,
+ [hashtable]$VersionInfo = $null,
+ [switch]$Force
+ )
+
+ $platformConfig = $script:platforms[$Platform]
+ $platformDir = Join-Path $BuildDir $platformConfig.OutputSubDir
+
+ # Determine zip filename (with or without version)
+ if ($VersionInfo) {
+ $zipFileName = "$script:fileName.$($VersionInfo.FullSemVer).$Platform.zip"
+ } else {
+ $zipFileName = "$script:fileName.$Platform.zip"
+ }
+ $zipFilePath = Join-Path $BuildDir $zipFileName
+
+ # Check if zip already exists and force not specified
+ if ((Test-Path $zipFilePath) -and -not $Force) {
+ Write-Host " Using existing zip: $zipFilePath" -ForegroundColor Gray
+ return $zipFilePath
+ }
+
+ # Validate source files exist
+ $files = Get-ChildItem -Path $platformDir -Recurse -File -ErrorAction SilentlyContinue
+ if (-not $files) {
+ Write-Host " ERROR: No files found in $platformDir" -ForegroundColor Red
+ return $null
+ }
+
+ # Create zip
+ Write-Host " Creating zip archive: $zipFileName" -ForegroundColor Cyan
+ try {
+ if (Test-Path $zipFilePath) { Remove-Item $zipFilePath -Force }
+ Compress-Archive -Path "$platformDir\*" -DestinationPath $zipFilePath -Force
+ Write-Host " Zip created: $zipFilePath" -ForegroundColor Green
+ return $zipFilePath
+ } catch {
+ Write-Host " ERROR: Failed to create zip: $($_.Exception.Message)" -ForegroundColor Red
+ return $null
+ }
+}
+
+function Export-GodotPlatform {
+ <#
+ .SYNOPSIS
+ Exports a single platform build using Godot - simple and direct
+ #>
+ param(
+ [string]$Platform,
+ [string]$GodotPath,
+ [string]$BuildDir,
+ [hashtable]$VersionInfo = $null
+ )
+
+ $platformConfig = $script:platforms[$Platform]
+ $outputPath = Join-Path $BuildDir "$($platformConfig.OutputSubDir)\$script:fileName$($platformConfig.Extension)"
+
+ Write-Host "Exporting $Platform build..." -ForegroundColor Cyan
+ Write-Host " Export Name: $($platformConfig.ExportName)" -ForegroundColor Gray
+ Write-Host " Output: $outputPath" -ForegroundColor Gray
+ Write-Host ""
+
+ if (Test-Path $outputPath) { Remove-Item $outputPath -Force }
+
+ $timeStamp = (Get-Date).ToString('yyyyMMdd-HHmmss')
+ # Put log in parent build folder, not in platform subfolder (avoid including in zip)
+ $logPath = Join-Path $BuildDir "godot-export-$Platform-$timeStamp.log"
+
+ $exportName = $platformConfig.ExportName
+
+ Write-Host "--- Godot Export Output ---" -ForegroundColor DarkGray
+ Write-Host "Logging to: $logPath" -ForegroundColor DarkGray
+ Write-Host ""
+
+ # Save current encoding and set to UTF8 to handle Godot's Unicode output
+ $previousEncoding = [Console]::OutputEncoding
+ try {
+ [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
+
+ # Run Godot directly - output streams to console and gets logged
+ & $GodotPath --headless --export-release $exportName $outputPath 2>&1 | Tee-Object -FilePath $logPath | ForEach-Object { Write-Host $_ }
+ } catch {
+ Write-Host " ERROR: Failed to execute Godot: $($_.Exception.Message)" -ForegroundColor Red
+ return $false
+ } finally {
+ # Restore previous encoding
+ [Console]::OutputEncoding = $previousEncoding
+ }
+
+ Write-Host ""
+ Write-Host "--- Export command completed ---" -ForegroundColor DarkGray
+ Write-Host ""
+
+ # Wait for the file to be created and stabilize
+ $success = Wait-ForExportCompletion -OutputPath $outputPath -TimeoutSeconds 30
+
+ if ($success) {
+ Write-Host " $Platform export completed successfully!" -ForegroundColor Green
+
+ # Create zip file after successful export (with version if provided)
+ $zipPath = Create-PlatformZip -Platform $Platform -BuildDir $BuildDir -VersionInfo $VersionInfo -Force
+ if (-not $zipPath) {
+ Write-Host " WARNING: Export succeeded but zip creation failed" -ForegroundColor Yellow
+ }
+ } else {
+ Write-Host " ERROR: $Platform export may have failed!" -ForegroundColor Red
+ Write-Host " Check log: $logPath" -ForegroundColor Yellow
+ }
+
+ return $success
+}
+
+function Publish-PlatformBuild {
+ <#
+ .SYNOPSIS
+ Publishes a platform build to itch.io
+ #>
+ param(
+ [string]$Platform,
+ [hashtable]$VersionInfo,
+ [string]$BuildDir,
+ [string]$ReleaseDir,
+ [string]$ButlerPath
+ )
+
+ $platformConfig = $script:platforms[$Platform]
+ $butlerTarget = "maddoscientisto/cirno-no-reason:$Platform$($VersionInfo.PreReleaseLabel)"
+
+ Write-Host "Publishing $Platform build..." -ForegroundColor Cyan
+
+ # Ensure zip exists with version number (create if missing)
+ $zipFilePath = Create-PlatformZip -Platform $Platform -BuildDir $BuildDir -VersionInfo $VersionInfo
+ if (-not $zipFilePath) {
+ Write-Host " ERROR: Failed to get or create zip file" -ForegroundColor Red
+ return $false
+ }
+
+ # Ensure release directory exists
+ if (!(Test-Path $ReleaseDir)) {
+ New-Item -ItemType Directory -Path $ReleaseDir | Out-Null
+ }
+
+ # Copy versioned zip to release directory
+ $zipFileName = Split-Path $zipFilePath -Leaf
+ $releaseZipPath = Join-Path $ReleaseDir $zipFileName
+ Copy-Item -Path $zipFilePath -Destination $releaseZipPath -Force
+ Write-Host " Copied to release: $zipFileName" -ForegroundColor Gray
+
+ # Push to itch.io
+ Write-Host " Pushing to itch.io: $butlerTarget" -ForegroundColor Gray
+ & $ButlerPath push $releaseZipPath $butlerTarget --userversion $VersionInfo.FullSemVer
+
+ if ($LASTEXITCODE -eq 0) {
+ Write-Host " $Platform published successfully!" -ForegroundColor Green
+ return $true
+ } else {
+ Write-Host " ERROR: Failed to publish $Platform build" -ForegroundColor Red
+ return $false
+ }
+}
+
+function Get-PlatformConfigurations {
+ <#
+ .SYNOPSIS
+ Returns platform configuration hashtable
+ #>
+ return $script:platforms
+}
+
+# Export functions
+Export-ModuleMember -Function Test-Prerequisites, Get-VersionInfo, Initialize-BuildDirectories, `
+ Update-ExportConfig, Wait-ForExportCompletion, Create-PlatformZip, Export-GodotPlatform, `
+ Publish-PlatformBuild, Get-PlatformConfigurations
diff --git a/Export.ps1 b/Export.ps1
index 92ee738d..c8ea3aa1 100644
--- a/Export.ps1
+++ b/Export.ps1
@@ -1,54 +1,46 @@
-# Define paths
-$gitVersionPath = "dotnet-gitversion.exe"
+# Export Script for Cirno No Reason
+# Exports game builds for Windows and Linux platforms
+# Import the module
+$modulePath = Join-Path $PSScriptRoot "CirnoBuild.psm1"
+Import-Module $modulePath -Force
+# Configuration
$godotPath = $env:GODOT
$buildDir = ".\build"
-$configFile = "export_presets.cfg"
-$zipOutputDir = ".\release"
-$fileName = "Cirno_No_Reason"
-
+$platforms = Get-PlatformConfigurations
+# Validate prerequisites
+$prereqResult = Test-Prerequisites -GodotPath $godotPath -SkipButler
+if (-not $prereqResult.Valid) {
+ exit 1
+}
+# Use resolved path if available
+if ($prereqResult.ResolvedGodotPath) {
+ $godotPath = $prereqResult.ResolvedGodotPath
+}
+Write-Host "Using Godot at: $godotPath" -ForegroundColor Green
+Write-Host ""
# Step 1: Clear the build directory
-if (Test-Path $buildDir) {
- Remove-Item "$buildDir\*" -Recurse -Force
-} else {
- New-Item -ItemType Directory -Path $buildDir | Out-Null
-}
-
-New-Item -ItemType Directory -Path $buildDir\win | Out-Null
-New-Item -ItemType Directory -Path $buildDir\linux | Out-Null
-
+Write-Host "Clearing build directory..."
+Initialize-BuildDirectories -PlatformsToBuild @("win", "linux") -BuildDir $buildDir
# Step 2: Get version data from GitVersion
-$gitVersionOutput = & $gitVersionPath | ConvertFrom-Json
-$assemblySemFileVer = $gitVersionOutput.AssemblySemFileVer
-$assemblySemVer = $gitVersionOutput.AssemblySemVer
-$fullSemVer = $gitVersionOutput.FullSemVer
-
-# Step 3: Set environment variables for use in the build process
-[System.Environment]::SetEnvironmentVariable("GIT_ASSEMBLY_SEM_FILE_VER", $assemblySemFileVer, [System.EnvironmentVariableTarget]::Process)
-[System.Environment]::SetEnvironmentVariable("GIT_ASSEMBLY_SEM_VER", $assemblySemVer, [System.EnvironmentVariableTarget]::Process)
-
-Write-Host "Set environment variables:"
-Write-Host " GIT_ASSEMBLY_SEM_FILE_VER = $assemblySemFileVer"
-Write-Host " GIT_ASSEMBLY_SEM_VER = $assemblySemVer"
-
+$versionInfo = Get-VersionInfo
# Step 3: Update export_presets.cfg
-if (Test-Path $configFile) {
- (Get-Content $configFile) `
- -replace 'application/file_version="[^"]*"', "application/file_version=`"$assemblySemFileVer`"" `
- -replace 'application/product_version="[^"]*"', "application/product_version=`"$assemblySemVer`"" `
- | Set-Content $configFile
-} else {
- Write-Host "Warning: $configFile not found!"
+Update-ExportConfig -VersionInfo $versionInfo
+# Step 4: Export builds
+$results = @{}
+foreach ($platformKey in $platforms.Keys) {
+ Write-Host ""
+ $results[$platformKey] = Export-GodotPlatform -Platform $platformKey `
+ -GodotPath $godotPath `
+ -BuildDir $buildDir `
+ -VersionInfo $versionInfo
}
-
-# Step 4: Export the build
-#& $godotPath --headless --export-release "Windows Desktop" "$buildDir\win\$fileName.exe"
-
-#& $godotPath --headless --export-release "Linux" "$buildDir\linux\$fileName.x86_64"
-
-# Step 4: Export the Windows build via CMD in the same window
-$winExportCmd = "`"$godotPath`" --headless --export-release `"Windows Desktop`" `"$buildDir\win\$fileName.exe`""
-& cmd.exe /c $winExportCmd
-
-# Step 5: Export the Linux build via CMD in the same window
-$linuxExportCmd = "`"$godotPath`" --headless --export-release `"Linux`" `"$buildDir\linux\$fileName.x86_64`""
-& cmd.exe /c $linuxExportCmd
\ No newline at end of file
+Write-Host ""
+Write-Host "=====================================" -ForegroundColor Cyan
+Write-Host " Export Summary" -ForegroundColor Cyan
+Write-Host "=====================================" -ForegroundColor Cyan
+foreach ($platformKey in $results.Keys) {
+ $status = if ($results[$platformKey]) { "SUCCESS" } else { "FAILED" }
+ $color = if ($results[$platformKey]) { "Green" } else { "Red" }
+ Write-Host " $platformKey : $status" -ForegroundColor $color
+}
+Write-Host ""
diff --git a/Publish.ps1 b/Publish.ps1
index 3e146083..ccc4904f 100644
--- a/Publish.ps1
+++ b/Publish.ps1
@@ -1,45 +1,57 @@
-$butlerPath = "F:\Apps\butler\butler.exe"
-$zipOutputDir = ".\release"
-$fileName = "Cirno_No_Reason"
-$gitVersionPath = "dotnet-gitversion.exe"
+# Publish Script for Cirno No Reason
+# Publishes builds to itch.io using Butler
+
+# Import the module
+$modulePath = Join-Path $PSScriptRoot "CirnoBuild.psm1"
+Import-Module $modulePath -Force
+
+# Configuration
+$butlerPath = "F:\Apps\butler\butler.exe"
+$releaseDir = ".\release"
$buildDir = ".\build"
+$godotPath = $env:GODOT
+$platforms = Get-PlatformConfigurations
-$gitVersionOutput = & $gitVersionPath | ConvertFrom-Json
-$assemblySemFileVer = $gitVersionOutput.AssemblySemFileVer
-$assemblySemVer = $gitVersionOutput.AssemblySemVer
-$fullSemVer = $gitVersionOutput.FullSemVer
-$PreReleaseLabel = $gitVersionOutput.PreReleaseLabelWithDash
+# Validate prerequisites
+$prereqResult = Test-Prerequisites -GodotPath $godotPath -ButlerPath $butlerPath
+if (-not $prereqResult.Valid) {
+ exit 1
+}
-#$zipFileName = "$fileName.$fullSemVer.win.zip"
-#$zipFileNameLinux = "$fileName.$fullSemVer.linux.zip"
-#$zipFilePath = "$zipOutputDir\$zipFileName"
-#$zipFilePathLinux = "$zipOutputDir\$zipFileNameLinux"
+# Use resolved path if available
+if ($prereqResult.ResolvedGodotPath) {
+ $godotPath = $prereqResult.ResolvedGodotPath
+}
+
+Write-Host "Getting version information..."
+$versionInfo = Get-VersionInfo
+
+Write-Host ""
# Ensure output directory exists
-if (!(Test-Path $zipOutputDir)) {
- New-Item -ItemType Directory -Path $zipOutputDir | Out-Null
+if (!(Test-Path $releaseDir)) {
+ New-Item -ItemType Directory -Path $releaseDir | Out-Null
}
-function Handle-BuildArtifact {
- param (
- [string]$platform,
- [string]$label
- )
-
- $sourcePath = Join-Path $buildDir $platform
- $zipFileName = "$fileName.$fullSemVer.$platform.zip"
- $zipFilePath = Join-Path $zipOutputDir $zipFileName
- $butlerTarget = "maddoscientisto/cirno-no-reason:$platform$label"
-
- $files = Get-ChildItem -Path $sourcePath -Recurse -File -ErrorAction SilentlyContinue
- if ($files) {
- Compress-Archive -Path "$sourcePath\*" -DestinationPath $zipFilePath -Force
- Write-Host "$platform build completed and packaged as $zipFilePath"
- & $butlerPath push $zipFilePath $butlerTarget --userversion $fullSemVer
- } else {
- Write-Warning "$platform build folder is empty or missing: $sourcePath"
- }
+# Publish all platforms
+$results = @{}
+foreach ($platformKey in $platforms.Keys) {
+ $results[$platformKey] = Publish-PlatformBuild `
+ -Platform $platformKey `
+ -VersionInfo $versionInfo `
+ -BuildDir $buildDir `
+ -ReleaseDir $releaseDir `
+ -ButlerPath $butlerPath
+ Write-Host ""
}
-
-Handle-BuildArtifact -platform "win" -label $PreReleaseLabel
-Handle-BuildArtifact -platform "linux" -label $PreReleaseLabel
\ No newline at end of file
+# Summary
+Write-Host "=====================================" -ForegroundColor Cyan
+Write-Host " Publish Summary" -ForegroundColor Cyan
+Write-Host "=====================================" -ForegroundColor Cyan
+foreach ($platformKey in $results.Keys) {
+ $status = if ($results[$platformKey]) { "SUCCESS" } else { "FAILED" }
+ $color = if ($results[$platformKey]) { "Green" } else { "Red" }
+ $platformName = $platforms[$platformKey].ExportName
+ Write-Host " $platformName : $status" -ForegroundColor $color
+}
+Write-Host ""
diff --git a/TestGodotPath.ps1 b/TestGodotPath.ps1
new file mode 100644
index 00000000..7792eca8
--- /dev/null
+++ b/TestGodotPath.ps1
@@ -0,0 +1,111 @@
+# Test script to verify Godot PATH resolution
+# Run this to test if godot.exe can be found
+
+Write-Host "=====================================" -ForegroundColor Cyan
+Write-Host " Godot PATH Resolution Test" -ForegroundColor Cyan
+Write-Host "=====================================" -ForegroundColor Cyan
+Write-Host ""
+
+# Test 1: Check if godot.exe is in PATH
+Write-Host "Test 1: Checking if godot.exe is in PATH..." -ForegroundColor Cyan
+$godotCmd = Get-Command godot.exe -ErrorAction SilentlyContinue
+if ($godotCmd) {
+ Write-Host " ✓ Found: $($godotCmd.Source)" -ForegroundColor Green
+ $godotInPath = $godotCmd.Source
+} else {
+ Write-Host " ✗ Not found in PATH" -ForegroundColor Red
+ $godotInPath = $null
+}
+Write-Host ""
+
+# Test 2: Check GODOT environment variable
+Write-Host "Test 2: Checking GODOT environment variable..." -ForegroundColor Cyan
+if ($env:GODOT) {
+ Write-Host " ✓ GODOT = $env:GODOT" -ForegroundColor Green
+ if (Test-Path $env:GODOT) {
+ Write-Host " ✓ File exists" -ForegroundColor Green
+ } else {
+ Write-Host " ✗ File does not exist at that path" -ForegroundColor Red
+ }
+} else {
+ Write-Host " ⚠ GODOT environment variable not set" -ForegroundColor Yellow
+}
+Write-Host ""
+
+# Test 3: Import module and test resolution
+Write-Host "Test 3: Testing module resolution..." -ForegroundColor Cyan
+try {
+ $modulePath = Join-Path $PSScriptRoot "CirnoBuild.psm1"
+ Import-Module $modulePath -Force
+
+ if ($env:GODOT) {
+ $testPath = $env:GODOT
+ } elseif ($godotInPath) {
+ $testPath = "godot.exe"
+ } else {
+ Write-Host " ⚠ Cannot test - no Godot found" -ForegroundColor Yellow
+ Write-Host ""
+ Write-Host "=====================================" -ForegroundColor Cyan
+ Write-Host " Result: Godot not available" -ForegroundColor Red
+ Write-Host "=====================================" -ForegroundColor Cyan
+ exit 1
+ }
+
+ Write-Host " Testing with: $testPath" -ForegroundColor Gray
+ $result = Test-Prerequisites -GodotPath $testPath -SkipButler
+
+ if ($result.Valid) {
+ Write-Host " ✓ Prerequisites check passed" -ForegroundColor Green
+ if ($result.ResolvedGodotPath) {
+ Write-Host " ✓ Resolved to: $($result.ResolvedGodotPath)" -ForegroundColor Green
+ }
+ } else {
+ Write-Host " ✗ Prerequisites check failed" -ForegroundColor Red
+ }
+} catch {
+ Write-Host " ✗ Error: $($_.Exception.Message)" -ForegroundColor Red
+}
+Write-Host ""
+
+# Test 4: Verify Godot version
+Write-Host "Test 4: Checking Godot version..." -ForegroundColor Cyan
+if ($godotInPath) {
+ try {
+ $version = & $godotInPath --version 2>&1 | Select-Object -First 1
+ Write-Host " ✓ Version: $version" -ForegroundColor Green
+ } catch {
+ Write-Host " ✗ Could not get version" -ForegroundColor Red
+ }
+} elseif ($env:GODOT -and (Test-Path $env:GODOT)) {
+ try {
+ $version = & $env:GODOT --version 2>&1 | Select-Object -First 1
+ Write-Host " ✓ Version: $version" -ForegroundColor Green
+ } catch {
+ Write-Host " ✗ Could not get version" -ForegroundColor Red
+ }
+} else {
+ Write-Host " ⚠ Skipped - no Godot path available" -ForegroundColor Yellow
+}
+Write-Host ""
+
+# Summary
+Write-Host "=====================================" -ForegroundColor Cyan
+Write-Host " Summary" -ForegroundColor Cyan
+Write-Host "=====================================" -ForegroundColor Cyan
+
+if ($godotInPath -or ($env:GODOT -and (Test-Path $env:GODOT))) {
+ Write-Host "✓ Godot is available and should work with build scripts" -ForegroundColor Green
+ Write-Host ""
+ Write-Host "You can now run:" -ForegroundColor Cyan
+ Write-Host " .\BuildPublish.bat" -ForegroundColor White
+ Write-Host " .\BuildPublish.ps1" -ForegroundColor White
+ Write-Host " .\Export.ps1" -ForegroundColor White
+} else {
+ Write-Host "✗ Godot is not properly configured" -ForegroundColor Red
+ Write-Host ""
+ Write-Host "To fix, do one of the following:" -ForegroundColor Yellow
+ Write-Host " 1. Add godot.exe to your PATH" -ForegroundColor White
+ Write-Host " 2. Set GODOT environment variable to full path" -ForegroundColor White
+ Write-Host " Example: `$env:GODOT = 'C:\Path\To\godot.exe'" -ForegroundColor Gray
+}
+Write-Host ""
diff --git a/VerifySetup.ps1 b/VerifySetup.ps1
new file mode 100644
index 00000000..39fad40f
--- /dev/null
+++ b/VerifySetup.ps1
@@ -0,0 +1,146 @@
+# Verification script for build environment setup
+
+Write-Host ""
+Write-Host "=====================================" -ForegroundColor Cyan
+Write-Host " Build Environment Verification" -ForegroundColor Cyan
+Write-Host "=====================================" -ForegroundColor Cyan
+Write-Host ""
+
+$allGood = $true
+
+# Check GODOT environment variable
+Write-Host "Checking GODOT environment variable..." -ForegroundColor Cyan
+if ([string]::IsNullOrWhiteSpace($env:GODOT)) {
+ Write-Host " ✗ GODOT environment variable is not set" -ForegroundColor Red
+ Write-Host " Run: `$env:GODOT = 'C:\Path\To\Godot.exe'" -ForegroundColor Yellow
+ $allGood = $false
+} else {
+ Write-Host " ✓ GODOT = $env:GODOT" -ForegroundColor Green
+
+ if (Test-Path $env:GODOT) {
+ Write-Host " ✓ Godot executable exists" -ForegroundColor Green
+
+ try {
+ $version = & $env:GODOT --version 2>&1 | Select-Object -First 1
+ Write-Host " ✓ Version: $version" -ForegroundColor Green
+ } catch {
+ Write-Host " ⚠ Could not get Godot version" -ForegroundColor Yellow
+ }
+ } else {
+ Write-Host " ✗ Godot executable not found at specified path" -ForegroundColor Red
+ $allGood = $false
+ }
+}
+Write-Host ""
+
+# Check GitVersion
+Write-Host "Checking GitVersion..." -ForegroundColor Cyan
+$gitVersionCmd = Get-Command dotnet-gitversion -ErrorAction SilentlyContinue
+if ($gitVersionCmd) {
+ Write-Host " ✓ GitVersion is installed" -ForegroundColor Green
+ try {
+ $gitVersionTest = & dotnet-gitversion /version 2>&1 | Select-Object -First 1
+ Write-Host " ✓ Version: $gitVersionTest" -ForegroundColor Green
+ } catch {
+ Write-Host " ⚠ GitVersion found but may have issues" -ForegroundColor Yellow
+ }
+} else {
+ Write-Host " ✗ GitVersion not found" -ForegroundColor Red
+ Write-Host " Install: dotnet tool install --global GitVersion.Tool" -ForegroundColor Yellow
+ $allGood = $false
+}
+Write-Host ""
+
+# Check Butler (optional)
+Write-Host "Checking Butler (optional, for publishing)..." -ForegroundColor Cyan
+$butlerPath = "F:\Apps\butler\butler.exe"
+if (Test-Path $butlerPath) {
+ Write-Host " ✓ Butler found at: $butlerPath" -ForegroundColor Green
+ try {
+ $butlerVersion = & $butlerPath -V 2>&1 | Select-Object -First 1
+ Write-Host " ✓ Version: $butlerVersion" -ForegroundColor Green
+ } catch {
+ Write-Host " ⚠ Butler found but may have issues" -ForegroundColor Yellow
+ }
+} else {
+ Write-Host " ⚠ Butler not found (only needed for publishing to itch.io)" -ForegroundColor Yellow
+ Write-Host " Download: https://itch.io/docs/butler/" -ForegroundColor Gray
+}
+Write-Host ""
+
+# Check export_presets.cfg
+Write-Host "Checking export configuration..." -ForegroundColor Cyan
+if (Test-Path "export_presets.cfg") {
+ Write-Host " ✓ export_presets.cfg exists" -ForegroundColor Green
+
+ $presetContent = Get-Content "export_presets.cfg" -Raw
+
+ if ($presetContent -match 'name="Windows Desktop"') {
+ Write-Host " ✓ Windows Desktop preset found" -ForegroundColor Green
+ } else {
+ Write-Host " ✗ Windows Desktop preset not found" -ForegroundColor Red
+ Write-Host " Configure in Godot: Project → Export..." -ForegroundColor Yellow
+ $allGood = $false
+ }
+
+ if ($presetContent -match 'name="Linux"') {
+ Write-Host " ✓ Linux preset found" -ForegroundColor Green
+ } else {
+ Write-Host " ✗ Linux preset not found" -ForegroundColor Red
+ Write-Host " Configure in Godot: Project → Export..." -ForegroundColor Yellow
+ $allGood = $false
+ }
+} else {
+ Write-Host " ✗ export_presets.cfg not found" -ForegroundColor Red
+ Write-Host " Configure export presets in Godot first" -ForegroundColor Yellow
+ $allGood = $false
+}
+Write-Host ""
+
+# Check build directories
+Write-Host "Checking directory structure..." -ForegroundColor Cyan
+if (Test-Path ".\build") {
+ Write-Host " ✓ build directory exists" -ForegroundColor Green
+} else {
+ Write-Host " ⚠ build directory will be created on first run" -ForegroundColor Gray
+}
+
+if (Test-Path ".\release") {
+ Write-Host " ✓ release directory exists" -ForegroundColor Green
+} else {
+ Write-Host " ⚠ release directory will be created on first publish" -ForegroundColor Gray
+}
+Write-Host ""
+
+# Check if in git repository
+Write-Host "Checking Git repository..." -ForegroundColor Cyan
+if (Test-Path ".git") {
+ Write-Host " ✓ Git repository detected" -ForegroundColor Green
+
+ try {
+ $gitBranch = git rev-parse --abbrev-ref HEAD 2>&1
+ Write-Host " ✓ Current branch: $gitBranch" -ForegroundColor Green
+ } catch {
+ Write-Host " ⚠ Could not get git branch" -ForegroundColor Yellow
+ }
+} else {
+ Write-Host " ⚠ Not a git repository (GitVersion may not work properly)" -ForegroundColor Yellow
+}
+Write-Host ""
+
+# Summary
+Write-Host "=====================================" -ForegroundColor Cyan
+if ($allGood) {
+ Write-Host " ✓ Environment Setup Complete!" -ForegroundColor Green
+ Write-Host " You can now run BuildPublish.bat" -ForegroundColor Green
+} else {
+ Write-Host " ✗ Setup Incomplete" -ForegroundColor Red
+ Write-Host " Please fix the issues above" -ForegroundColor Yellow
+ Write-Host " See SETUP_GUIDE.md for details" -ForegroundColor Yellow
+}
+Write-Host "=====================================" -ForegroundColor Cyan
+Write-Host ""
+
+if (-not $allGood) {
+ exit 1
+}