Files
bd2/tools/python/start-official-capture.ps1
T
2026-09-21 09:53:46 +08:00

112 lines
4.6 KiB
PowerShell

param(
[Parameter(Mandatory)]
[string]$GameDir,
[Parameter(Mandatory)]
[string]$LocalClientDir,
[string]$SharedDataDir,
[switch]$Wait
)
$ErrorActionPreference = 'Stop'
$GameDir = [IO.Path]::GetFullPath($GameDir)
$LocalClientDir = [IO.Path]::GetFullPath($LocalClientDir)
if (-not $SharedDataDir) {
$localAppData = [Environment]::GetFolderPath([Environment+SpecialFolder]::LocalApplicationData)
$SharedDataDir = Join-Path (Split-Path -Parent $localAppData) 'LocalLow\Gamfs\BrownDust II'
}
$SharedDataDir = [IO.Path]::GetFullPath($SharedDataDir)
$exe = Join-Path $GameDir 'BrownDust II.exe'
$pluginDir = Join-Path $GameDir 'BepInEx\plugins'
$localRes = Join-Path $pluginDir 'PluginLocalRes.dll'
$capturePlugin = Join-Path $pluginDir 'BD2CaptureEnvironment.dll'
$identityPlugin = Join-Path $pluginDir 'BD2LocalIdentity.dll'
$doorstop = Join-Path $GameDir 'doorstop_config.ini'
$isolatedData = Join-Path $GameDir 'IsolatedUserData'
$sharedGameData = Join-Path $SharedDataDir 'Data\t'
$stagedCapturePlugin = Join-Path $PSScriptRoot '..\..\plugins\CaptureEnvironment\bin\Release\netstandard2.1\BD2CaptureEnvironment.dll'
if (Get-Process -Name 'BrownDust II' -ErrorAction SilentlyContinue) {
throw 'BrownDust II is already running. Exit it before starting the isolated official client.'
}
foreach ($requiredDirectory in @($GameDir, $LocalClientDir, $SharedDataDir, $sharedGameData)) {
if (-not (Test-Path -LiteralPath $requiredDirectory -PathType Container)) {
throw "Required directory is missing: $requiredDirectory"
}
}
if (Test-Path -LiteralPath $stagedCapturePlugin -PathType Leaf) {
$installedHash = if (Test-Path -LiteralPath $capturePlugin -PathType Leaf) {
(Get-FileHash -LiteralPath $capturePlugin -Algorithm SHA256).Hash
}
$stagedHash = (Get-FileHash -LiteralPath $stagedCapturePlugin -Algorithm SHA256).Hash
if ($installedHash -ne $stagedHash) {
New-Item -ItemType Directory -Force -Path $pluginDir | Out-Null
Copy-Item -LiteralPath $stagedCapturePlugin -Destination $capturePlugin -Force
Write-Host "Updated capture plugin from staged build ($stagedHash)."
}
}
foreach ($required in @($exe, $doorstop, $localRes, $capturePlugin)) {
if (-not (Test-Path -LiteralPath $required -PathType Leaf)) {
throw "Required file is missing: $required"
}
}
if (Test-Path -LiteralPath $identityPlugin) {
throw "Unsafe plugin found in official environment: $identityPlugin"
}
$unexpectedIdentity = Get-ChildItem -LiteralPath (Join-Path $GameDir 'BepInEx') `
-Recurse -File -Filter 'BD2LocalIdentity.dll' -ErrorAction SilentlyContinue
if ($unexpectedIdentity) {
throw "BD2LocalIdentity.dll must not exist anywhere in the official environment."
}
$sharedStaticPaths = @{
(Join-Path $isolatedData 'SoundData') = (Join-Path $SharedDataDir 'SoundData')
(Join-Path $isolatedData 'com.unity.addressables') = (Join-Path $SharedDataDir 'com.unity.addressables')
(Join-Path $isolatedData 'VideoData') = (Join-Path $SharedDataDir 'VideoData')
(Join-Path $GameDir 'BrownDust II_Data\StreamingAssets\aa') = (Join-Path $LocalClientDir 'BrownDust II_Data\StreamingAssets\aa')
}
foreach ($link in $sharedStaticPaths.GetEnumerator()) {
$item = Get-Item -LiteralPath $link.Key -Force -ErrorAction SilentlyContinue
if (-not $item -or $item.LinkType -ne 'Junction') {
throw "Shared static-data junction is missing: $($link.Key)"
}
$actualTarget = [IO.Path]::GetFullPath([string]$item.Target)
$expectedTarget = [IO.Path]::GetFullPath([string]$link.Value)
if ($actualTarget -ne $expectedTarget) {
throw "Unexpected junction target for $($link.Key): $actualTarget"
}
}
New-Item -ItemType Directory -Force -Path $isolatedData | Out-Null
$unityLog = Join-Path $isolatedData 'Player.log'
$process = Start-Process -FilePath $exe -WorkingDirectory $GameDir `
-ArgumentList @(
'-logFile', ('"' + $unityLog + '"'),
'-bd2SharedGameData', ('"' + $sharedGameData + '"')
) -PassThru
Write-Host "Started isolated official client (PID $($process.Id))."
Write-Host "BepInEx log: $(Join-Path $GameDir 'BepInEx\LogOutput.log')"
Write-Host "Capture root: $(Join-Path $GameDir 'Capture')"
Write-Host "Isolated data: $isolatedData"
if ($Wait) {
$process.WaitForExit()
Write-Host "Client exited with code $($process.ExitCode)."
$latest = Get-ChildItem -LiteralPath (Join-Path $GameDir 'Capture') `
-Directory -ErrorAction SilentlyContinue |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
if ($latest) {
Write-Host "Latest capture: $($latest.FullName)"
}
}