[CmdletBinding()]
param(
[ValidateSet('Debug', 'Release')][string]$Configuration = 'Release',
[switch]$SkipTests,
[switch]$NoRestore
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
$workspace = $PSScriptRoot
$projects = @('AutoMiningScript', 'AutoMiningFleet', 'AutoMiningMarker', 'AutoMiningWatchdog')
$languages = @('zh-CN', 'en-US')
$exports = [Collections.Generic.List[object]]::new()
$buildStarted = [DateTime]::UtcNow
Push-Location -LiteralPath $workspace
try {
if (-not $NoRestore) {
& dotnet restore AutoMiningScript.slnx --nologo
if ($LASTEXITCODE -ne 0) { throw 'NuGet restore failed.' }
}
& (Join-Path $workspace 'tools/Test-Localization.ps1')
foreach ($language in $languages) {
foreach ($project in $projects) {
$projectFile = Join-Path $project ($project + '.csproj')
& dotnet build $projectFile --configuration $Configuration --no-restore --nologo "-p:ScriptLanguage=$language"
if ($LASTEXITCODE -ne 0) { throw "Build or MDK packaging failed: $project ($language)" }
$scriptPath = Join-Path $workspace "dist/$language/$project/script.cs"
if (-not (Test-Path -LiteralPath $scriptPath)) { throw "MDK did not export $scriptPath" }
$artifact = Get-Item -LiteralPath $scriptPath
if ($artifact.LastWriteTimeUtc -lt $buildStarted.AddSeconds(-2)) { throw "MDK output is stale: $scriptPath" }
$text = [IO.File]::ReadAllText($scriptPath)
if (-not $text.Contains('XFE AMS') -or -not $text.Contains($language)) { throw "Missing XFE AMS brand or wrong-language export: $scriptPath" }
if ($text.Length -gt 100000) { throw "$project exceeds the programmable block 100000-character limit ($($text.Length))." }
if ($text -match 'XFEExtension|IProgramBase|SetAutoPilotEnabled\(true\)|AddWaypoint\(') { throw "$project contains an external helper dependency or remote autopilot navigation." }
# Compile the exported text with the game's standard namespace imports. This catches
# names that compile in the project but disappear when MDK strips custom using lines.
$verificationDirectory = Join-Path $workspace "obj/packed-verification/$language/$project"
New-Item -ItemType Directory -Path $verificationDirectory -Force | Out-Null
$prelude = @'
using Sandbox.Game.EntityComponents;
using Sandbox.ModAPI.Ingame;
using Sandbox.ModAPI.Interfaces;
using SpaceEngineers.Game.ModAPI.Ingame;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using VRage;
using VRage.Collections;
using VRage.Game;
using VRage.Game.Components;
using VRage.Game.GUI.TextPanel;
using VRage.Game.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame.Utilities;
using VRage.Game.ObjectBuilders.Definitions;
using VRageMath;
namespace PackedVerification { public sealed class Program : MyGridProgram {
'@
[IO.File]::WriteAllText((Join-Path $verificationDirectory 'Packed.cs'), $prelude + "`n" + $text + "`n} }", [Text.UTF8Encoding]::new($false))
$verificationProject = @'
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<LangVersion>6</LangVersion>
<PlatformTarget>x64</PlatformTarget>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup><PackageReference Include="XFEExtension.SpaceEngineers.ScriptingHelper" Version="1.0.3" PrivateAssets="all" /></ItemGroup>
</Project>
'@
$verificationProjectPath = Join-Path $verificationDirectory 'Packed.csproj'
[IO.File]::WriteAllText($verificationProjectPath, $verificationProject, [Text.UTF8Encoding]::new($false))
& dotnet build $verificationProjectPath --configuration $Configuration --nologo --verbosity quiet
if ($LASTEXITCODE -ne 0) { throw "Exported programmable-block script does not compile with game imports: $project" }
$exports.Add([ordered]@{ project = $project; language = $language; path = "$language/$project/script.cs"; characters = $text.Length; sha256 = (Get-FileHash -LiteralPath $scriptPath -Algorithm SHA256).Hash.ToLowerInvariant() })
Write-Host "XFE AMS / $language / $project : $($text.Length) characters / 100000" -ForegroundColor Green
}
if (-not $SkipTests) {
$testProject = Join-Path $workspace 'AutoMiningScript.Tests/AutoMiningScript.Tests.csproj'
if (-not (Test-Path -LiteralPath $testProject)) { throw 'Logic test project is missing. Use -SkipTests only for packaging development.' }
& dotnet test $testProject --configuration $Configuration --nologo "-p:ScriptLanguage=$language" --logger "trx;LogFileName=$language.trx" --results-directory (Join-Path $workspace 'TestResults')
if ($LASTEXITCODE -ne 0) { throw "Logic tests failed: $language" }
}
}
$manifest = [ordered]@{ product = 'XFE AMS'; generatedUtc = [DateTime]::UtcNow.ToString('o'); configuration = $Configuration; logicTestsRun = (-not $SkipTests); exports = $exports.ToArray() }
[IO.File]::WriteAllText((Join-Path $workspace 'dist/manifest.json'), ($manifest | ConvertTo-Json -Depth 5), [Text.UTF8Encoding]::new($false))
Write-Host 'XFE AMS: eight scripts exported to dist/zh-CN and dist/en-US; checksums in dist/manifest.json. In-game validation remains separate.' -ForegroundColor Cyan
}
finally { Pop-Location }
[CmdletBinding()]
param(
[ValidateSet('Debug', 'Release')][string]$Configuration = 'Release',
[switch]$SkipTests,
[switch]$NoRestore
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
$workspace = $PSScriptRoot
$projects = @('AutoMiningScript', 'AutoMiningFleet', 'AutoMiningMarker', 'AutoMiningWatchdog')
$languages = @('zh-CN', 'en-US')
$exports = [Collections.Generic.List[object]]::new()
$buildStarted = [DateTime]::UtcNow
Push-Location -LiteralPath $workspace
try {
if (-not $NoRestore) {
& dotnet restore AutoMiningScript.slnx --nologo
if ($LASTEXITCODE -ne 0) { throw 'NuGet restore failed.' }
}
& (Join-Path $workspace 'tools/Test-Localization.ps1')
foreach ($language in $languages) {
foreach ($project in $projects) {
$projectFile = Join-Path $project ($project + '.csproj')
& dotnet build $projectFile --configuration $Configuration --no-restore --nologo "-p:ScriptLanguage=$language"
if ($LASTEXITCODE -ne 0) { throw "Build or MDK packaging failed: $project ($language)" }
$scriptPath = Join-Path $workspace "dist/$language/$project/script.cs"
if (-not (Test-Path -LiteralPath $scriptPath)) { throw "MDK did not export $scriptPath" }
$artifact = Get-Item -LiteralPath $scriptPath
if ($artifact.LastWriteTimeUtc -lt $buildStarted.AddSeconds(-2)) { throw "MDK output is stale: $scriptPath" }
$text = [IO.File]::ReadAllText($scriptPath)
if (-not $text.Contains('XFE AMS') -or -not $text.Contains($language)) { throw "Missing XFE AMS brand or wrong-language export: $scriptPath" }
if ($text.Length -gt 100000) { throw "$project exceeds the programmable block 100000-character limit ($($text.Length))." }
if ($text -match 'XFEExtension|IProgramBase|SetAutoPilotEnabled\(true\)|AddWaypoint\(') { throw "$project contains an external helper dependency or remote autopilot navigation." }
# Compile the exported text with the game's standard namespace imports. This catches
# names that compile in the project but disappear when MDK strips custom using lines.
$verificationDirectory = Join-Path $workspace "obj/packed-verification/$language/$project"
New-Item -ItemType Directory -Path $verificationDirectory -Force | Out-Null
$prelude = @'
using Sandbox.Game.EntityComponents;
using Sandbox.ModAPI.Ingame;
using Sandbox.ModAPI.Interfaces;
using SpaceEngineers.Game.ModAPI.Ingame;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using VRage;
using VRage.Collections;
using VRage.Game;
using VRage.Game.Components;
using VRage.Game.GUI.TextPanel;
using VRage.Game.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame.Utilities;
using VRage.Game.ObjectBuilders.Definitions;
using VRageMath;
namespace PackedVerification { public sealed class Program : MyGridProgram {
'@
[IO.File]::WriteAllText((Join-Path $verificationDirectory 'Packed.cs'), $prelude + "`n" + $text + "`n} }", [Text.UTF8Encoding]::new($false))
$verificationProject = @'
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<LangVersion>6</LangVersion>
<PlatformTarget>x64</PlatformTarget>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup><PackageReference Include="XFEExtension.SpaceEngineers.ScriptingHelper" Version="1.0.3" PrivateAssets="all" /></ItemGroup>
</Project>
'@
$verificationProjectPath = Join-Path $verificationDirectory 'Packed.csproj'
[IO.File]::WriteAllText($verificationProjectPath, $verificationProject, [Text.UTF8Encoding]::new($false))
& dotnet build $verificationProjectPath --configuration $Configuration --nologo --verbosity quiet
if ($LASTEXITCODE -ne 0) { throw "Exported programmable-block script does not compile with game imports: $project" }
$exports.Add([ordered]@{ project = $project; language = $language; path = "$language/$project/script.cs"; characters = $text.Length; sha256 = (Get-FileHash -LiteralPath $scriptPath -Algorithm SHA256).Hash.ToLowerInvariant() })
Write-Host "XFE AMS / $language / $project : $($text.Length) characters / 100000" -ForegroundColor Green
}
if (-not $SkipTests) {
$testProject = Join-Path $workspace 'AutoMiningScript.Tests/AutoMiningScript.Tests.csproj'
if (-not (Test-Path -LiteralPath $testProject)) { throw 'Logic test project is missing. Use -SkipTests only for packaging development.' }
& dotnet test $testProject --configuration $Configuration --nologo "-p:ScriptLanguage=$language" --logger "trx;LogFileName=$language.trx" --results-directory (Join-Path $workspace 'TestResults')
if ($LASTEXITCODE -ne 0) { throw "Logic tests failed: $language" }
}
}
$manifest = [ordered]@{ product = 'XFE AMS'; generatedUtc = [DateTime]::UtcNow.ToString('o'); configuration = $Configuration; logicTestsRun = (-not $SkipTests); exports = $exports.ToArray() }
[IO.File]::WriteAllText((Join-Path $workspace 'dist/manifest.json'), ($manifest | ConvertTo-Json -Depth 5), [Text.UTF8Encoding]::new($false))
Write-Host 'XFE AMS: eight scripts exported to dist/zh-CN and dist/en-US; checksums in dist/manifest.json. In-game validation remains separate.' -ForegroundColor Cyan
}
finally { Pop-Location }