Deploy: pod install scaffold -- supervisor entry-point, postinstall, packaging
Network-agnostic, air-gapped pod install for the two DOSBox titles (BT/RP 4.10), fitting the existing TeslaConsole/TeslaLauncher pod-bay architecture. emulator/DEPLOYMENT-PLAN.md Full design: bridge on the one NIC (pods form a source-proven P2P TCP mesh, so NAT/slirp is out); launcher keeps the bay IP, the DOSBox guest bridges at bayIP+100 (egg/mesh/game endpoint); two-edit +100 convention (postinstall + console DOSBox flag); static, air-gapped, <=32 pods. emulator/pod-launch/ (C# net8 supervising entry-point) Creates a Job Object (KILL_ON_JOB_CLOSE), launches DOSBox-X + the render bridge into it and blocks -- kill this process and both die (kernel-enforced, even on a hard TerminateProcess of a hung session; verified). Mode dispatch: bt/rp wired (also serve camera + live mission-review via egg hostType); review + diagnostics recognized but fail clean until their DOS launch args are known. emulator/deploy/ (install side) postinstall.bat (thin elevated wrapper) + configure.ps1 (NIC detect, realnic bind as a contiguous letter-leading GUID fragment, game IP = bayIP+100, stable MAC, render net_*.conf templates, stamp WATTCP.CFG my_ip) + tokenized conf templates + package.ps1 (assemble the zip). Render/bind/stamp + packaging verified against a scratch tree. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# deploy/ -- install-side artifacts
|
||||
|
||||
Sources for the self-contained, air-gapped pod install. See
|
||||
[`../DEPLOYMENT-PLAN.md`](../DEPLOYMENT-PLAN.md) for the full design.
|
||||
|
||||
## Files
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `postinstall.bat` | elevated entry TeslaLauncher runs after extraction: finds the package folder, installs bundled Npcap, calls `configure.ps1` |
|
||||
| `configure.ps1` | the per-pod step: detects the NIC + bay IP, derives the game IP = **bayIP+100**, binds DOSBox's pcap (`realnic`), renders the conf templates, stamps `WATTCP.CFG my_ip` |
|
||||
| `net_loop.conf.tmpl` | BattleTech conf template (looped netnub) |
|
||||
| `net_rp.conf.tmpl` | Red Planet conf template (single-shot) |
|
||||
| `package.ps1` | assembles the deployable zip from repo sources + a fresh self-contained `pod-launch` publish |
|
||||
|
||||
Template tokens filled at install: `@@ROOT@@` (package dir), `@@REALNIC@@` (this
|
||||
pod's NIC GUID fragment), `@@MACADDR@@` (stable MAC derived from the game IP).
|
||||
|
||||
## Packaged zip layout
|
||||
|
||||
The archive extracts to the games root (`C:\games`). Zip root = one package
|
||||
folder + `postinstall.bat`:
|
||||
|
||||
```
|
||||
C:\games\
|
||||
postinstall.bat <- from deploy/postinstall.bat
|
||||
TeslaPod410\ <- the single package folder (= ROOT)
|
||||
pod-launch.exe <- built from ../pod-launch (self-contained)
|
||||
dosbox-x.exe (+ DLLs)
|
||||
net_loop.conf.tmpl <- from deploy/ (rendered -> net_loop.conf)
|
||||
net_rp.conf.tmpl <- from deploy/ (rendered -> net_rp.conf)
|
||||
renderer.exe <- frozen renderer (OPEN: packaging w/ David)
|
||||
roms\awe32.raw
|
||||
ALPHA_1\... <- game content (incl. the WATTCP.CFG files)
|
||||
net-boot\... <- ODI/packet drivers, NET.CFG @340/INT10
|
||||
deploy\
|
||||
configure.ps1 <- from deploy/
|
||||
npcap.exe <- bundled Npcap silent installer (NOT in repo)
|
||||
vc_redist.x64.exe <- optional, if the DOSBox build needs it
|
||||
```
|
||||
|
||||
`postinstall.bat` derives `ROOT` as the single folder beside it, so the folder
|
||||
can be named per package.
|
||||
|
||||
## What runs at install (elevated, no network -- air-gapped)
|
||||
|
||||
1. `postinstall.bat` locates `ROOT`, runs `ROOT\deploy\npcap.exe /S`.
|
||||
2. `configure.ps1 -Root ROOT`:
|
||||
- finds the one static IPv4 (the **bay IP**) + its adapter GUID;
|
||||
- `realnic` = a contiguous, letter-leading fragment of a single GUID block
|
||||
(DOSBox reads a leading digit as an interface index; the fragment must be a
|
||||
substring of `\Device\NPF_{GUID}`);
|
||||
- **game IP = bay IP + 100** on the last octet (≤32 pods, bays `.1-.100`);
|
||||
- `macaddr` = `02:00:<game IP octets in hex>` (stable, locally-administered);
|
||||
- renders `*.conf.tmpl` -> `*.conf` (tokens filled);
|
||||
- stamps `my_ip = gameIP` into every `ALPHA_1\...\WATTCP.CFG`.
|
||||
3. `pod-launch.exe` (the supervisor) then selects + launches the rendered conf.
|
||||
|
||||
Verified against a scratch package tree: NIC detect, `realnic` (contiguous-match
|
||||
checked), `bayIP+100`, MAC, conf render, and WATTCP stamp all correct.
|
||||
|
||||
## Building the zip
|
||||
|
||||
```
|
||||
deploy\package.ps1 [-PackageName TeslaPod410] [-Npcap <installer>] `
|
||||
[-Renderer <exe>] [-VcRedist <exe>] [-NoContent] [-SkipBuild]
|
||||
```
|
||||
|
||||
Publishes `pod-launch` self-contained, stages the tree (postinstall.bat at the
|
||||
zip root + the package folder), and writes `emulator\dist\<PackageName>.zip`.
|
||||
`-NoContent` skips `ALPHA_1`/`net-boot` for a fast structural check. Externally-
|
||||
procured pieces are bundled only when their paths are passed (else flagged).
|
||||
|
||||
## Not yet in the repo / OPEN
|
||||
|
||||
- `npcap.exe` (licensed installer -- procured out-of-band) and any `vc_redist`.
|
||||
- The frozen `renderer.exe` (packaging decision with David; `pod-launch` falls
|
||||
back to `pyw live_bridge.py` when absent).
|
||||
- **DOSBox-X runtime DLL closure** (MinGW/SDL DLLs): none sit beside
|
||||
`dosbox-x.exe` in the dev tree -- it finds them via MSYS2 on PATH. The air-
|
||||
gapped package must bundle them; `package.ps1` copies any DLLs beside the exe
|
||||
and warns when there are none.
|
||||
- RP loop-vs-single-shot for retail parity (template currently mirrors dev).
|
||||
@@ -0,0 +1,86 @@
|
||||
# configure.ps1 -- the per-pod install step, called by postinstall.bat (elevated).
|
||||
# On THIS machine it: finds the NIC + its static IP (the bay IP), derives the
|
||||
# DOSBox game IP = bayIP + 100, binds DOSBox's pcap to the NIC, renders the
|
||||
# net_*.conf templates, and stamps the WATTCP.CFG my_ip. Air-gapped, static,
|
||||
# <=32 pods. See ../DEPLOYMENT-PLAN.md.
|
||||
param([Parameter(Mandatory = $true)][string]$Root)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
function Log($m) { Write-Host "[configure] $m" }
|
||||
|
||||
# --- prefix length -> dotted netmask -------------------------------------
|
||||
function PrefixToMask([int]$p) {
|
||||
$bits = ('1' * $p).PadRight(32, '0')
|
||||
$o = 0..3 | ForEach-Object { [Convert]::ToInt32($bits.Substring($_ * 8, 8), 2) }
|
||||
return ($o -join '.')
|
||||
}
|
||||
|
||||
# --- 1. the pod's NIC + bay IP (the one real static IPv4) ----------------
|
||||
$ip = Get-NetIPAddress -AddressFamily IPv4 |
|
||||
Where-Object { $_.IPAddress -notlike '127.*' -and $_.IPAddress -notlike '169.254.*' } |
|
||||
Sort-Object -Property SkipAsSource, InterfaceMetric |
|
||||
Select-Object -First 1
|
||||
if (-not $ip) { throw "no usable static IPv4 found on any adapter" }
|
||||
$bayIp = $ip.IPAddress
|
||||
$ifIndex = $ip.InterfaceIndex
|
||||
$adapter = Get-NetAdapter -InterfaceIndex $ifIndex
|
||||
$guid = $adapter.InterfaceGuid.Trim('{', '}')
|
||||
$mask = PrefixToMask $ip.PrefixLength
|
||||
Log "bay IP $bayIp/$($ip.PrefixLength) on '$($adapter.Name)' guid $guid"
|
||||
|
||||
# --- 2. realnic fragment. Must be a CONTIGUOUS substring of the pcap device
|
||||
# name (\Device\NPF_{GUID}, hyphens included), so take it from ONE
|
||||
# hyphen-delimited GUID block -- letter-leading (DOSBox reads a leading
|
||||
# DIGIT as an interface index) and length >= 6 for uniqueness. Longest. --
|
||||
$realnic = $null
|
||||
foreach ($blk in ($guid -split '-')) {
|
||||
$mm = [regex]::Match($blk, '[A-Fa-f][0-9A-Fa-f]{5,}')
|
||||
if ($mm.Success -and (-not $realnic -or $mm.Value.Length -gt $realnic.Length)) { $realnic = $mm.Value }
|
||||
}
|
||||
if (-not $realnic) { throw "no letter-leading >=6-char realnic fragment in any block of GUID $guid" }
|
||||
Log "realnic fragment = $realnic"
|
||||
|
||||
# --- 3. game IP = bay IP + 100 on the last octet -------------------------
|
||||
$o = $bayIp.Split('.')
|
||||
$last = [int]$o[3] + 100
|
||||
if ($last -gt 254) { throw "bay last octet $($o[3]) + 100 = $last overflows 254; keep bays <= .100" }
|
||||
$gameIp = "$($o[0]).$($o[1]).$($o[2]).$last"
|
||||
Log "game IP = $gameIp (bay + 100)"
|
||||
|
||||
# --- 4. stable locally-administered MAC from the game IP ------------------
|
||||
$mac = "02:00:{0:X2}:{1:X2}:{2:X2}:{3:X2}" -f [int]$o[0], [int]$o[1], [int]$o[2], $last
|
||||
Log "macaddr = $mac"
|
||||
|
||||
# --- 5. gateway/nameserver: the host's real gateway if set, else the host
|
||||
# itself (always up + on-subnet -> WATTCP's boot ARP resolves; never
|
||||
# actually routed, the mesh is same-subnet L2) -----------------------
|
||||
$gw = $null
|
||||
try { $gw = (Get-NetIPConfiguration -InterfaceIndex $ifIndex).IPv4DefaultGateway.NextHop } catch { }
|
||||
if (-not $gw) { $gw = $bayIp }
|
||||
Log "gateway/nameserver = $gw"
|
||||
|
||||
# --- 6. render the conf templates (@@ROOT@@/@@REALNIC@@/@@MACADDR@@) ------
|
||||
$tokens = @{ '@@ROOT@@' = $Root; '@@REALNIC@@' = $realnic; '@@MACADDR@@' = $mac }
|
||||
$tmpls = Get-ChildItem -Path $Root -Filter '*.conf.tmpl' -ErrorAction SilentlyContinue
|
||||
if (-not $tmpls) { throw "no *.conf.tmpl found in $Root" }
|
||||
foreach ($t in $tmpls) {
|
||||
$text = Get-Content -Path $t.FullName -Raw
|
||||
foreach ($k in $tokens.Keys) { $text = $text.Replace($k, $tokens[$k]) }
|
||||
$out = Join-Path $Root ($t.Name -replace '\.tmpl$', '')
|
||||
Set-Content -Path $out -Value $text -Encoding Ascii -NoNewline
|
||||
Log "rendered $($t.Name -replace '\.tmpl$','')"
|
||||
}
|
||||
|
||||
# --- 7. stamp WATTCP.CFG my_ip = game IP (all copies the game may read) ---
|
||||
$wattcp = @(
|
||||
(Join-Path $Root 'ALPHA_1\REL410\BT\WATTCP.CFG'),
|
||||
(Join-Path $Root 'ALPHA_1\REL410\RP\WATTCP.CFG'),
|
||||
(Join-Path $Root 'ALPHA_1\VGL_LABS\THISPOD\WATTCP.CFG')
|
||||
)
|
||||
$lines = @("my_ip = $gameIp", "netmask = $mask", "nameserver = $gw", "gateway = $gw")
|
||||
$stamped = 0
|
||||
foreach ($w in $wattcp) {
|
||||
if (Test-Path $w) { Set-Content -Path $w -Value $lines -Encoding Ascii; $stamped++; Log "stamped $w" }
|
||||
}
|
||||
if ($stamped -eq 0) { throw "no WATTCP.CFG found under $Root\ALPHA_1" }
|
||||
|
||||
Log "OK: bay=$bayIp game=$gameIp mac=$mac realnic=$realnic ($stamped WATTCP.CFG)"
|
||||
@@ -0,0 +1,58 @@
|
||||
# DEPLOY TEMPLATE -- rendered to net_loop.conf by deploy/configure.ps1 at install.
|
||||
# Tokens (filled by postinstall): @@ROOT@@ = package dir (C:\games\<folder>),
|
||||
# @@REALNIC@@ = this pod's NIC GUID fragment, @@MACADDR@@ = stable derived MAC.
|
||||
# BattleTech, GO.BAT-style netnub loop (pod stays connected + picks up missions).
|
||||
[sdl]
|
||||
output=opengl
|
||||
priority=highest,highest
|
||||
[dosbox]
|
||||
memsize=32
|
||||
machine=svga_s3
|
||||
[cpu]
|
||||
core=dynamic
|
||||
cputype=pentium
|
||||
cycles=max
|
||||
[ne2000]
|
||||
ne2000=true
|
||||
nicbase=340
|
||||
# IRQ 10, NOT 3: COM2 (plasma) owns IRQ 3 in-game.
|
||||
nicirq=10
|
||||
macaddr=@@MACADDR@@
|
||||
backend=pcap
|
||||
[ethernet, pcap]
|
||||
realnic=@@REALNIC@@
|
||||
[sblaster]
|
||||
sbtype=sb16
|
||||
sbbase=220
|
||||
irq=5
|
||||
dma=1
|
||||
hdma=5
|
||||
[mixer]
|
||||
rate=44100
|
||||
blocksize=1024
|
||||
prebuffer=60
|
||||
[serial]
|
||||
serial1=directserial realport:COM1 rxpollus:100 rxburst:16
|
||||
serial2=directserial realport:COM2
|
||||
[autoexec]
|
||||
mount c "@@ROOT@@\ALPHA_1"
|
||||
mount d "@@ROOT@@\net-boot"
|
||||
d:
|
||||
echo === loading NE2000 packet-driver stack (pcap/bridge, port 340) ===
|
||||
d:\lsl
|
||||
d:\ne2000
|
||||
d:\odipkt
|
||||
c:
|
||||
cd \rel410\bt
|
||||
set VIDEOFORMAT=svga
|
||||
set BLASTER=A220 I5 D1 H5 P330 T6
|
||||
c:\sb16\diagnose /s
|
||||
set BLASTER=A240 I7 D3 H6 P300 T6
|
||||
c:\sb16\diagnose /s
|
||||
set BLASTER=A220 I5 D1 H5 P330 T6
|
||||
set TEMP=c:\
|
||||
set HEAPSIZE=15000000
|
||||
set L4GAUGE=640x480x16
|
||||
call setenv.bat r f s p
|
||||
echo === entering GO.BAT-style netnub loop (waits for console missions) ===
|
||||
call d:\loop.bat
|
||||
@@ -0,0 +1,63 @@
|
||||
# DEPLOY TEMPLATE -- rendered to net_rp.conf by deploy/configure.ps1 at install.
|
||||
# Tokens (filled by postinstall): @@ROOT@@ = package dir (C:\games\<folder>),
|
||||
# @@REALNIC@@ = this pod's NIC GUID fragment, @@MACADDR@@ = stable derived MAC.
|
||||
# Red Planet 4.10, networked pod boot (console pushes the mission egg over TCP).
|
||||
# NOTE: single-shot netnub here (matches dev net_rp.conf); whether RP should loop
|
||||
# like BT for retail-parity is an OPEN deploy decision (see DEPLOYMENT-PLAN.md).
|
||||
[sdl]
|
||||
output=opengl
|
||||
priority=highest,highest
|
||||
[dosbox]
|
||||
memsize=32
|
||||
machine=svga_s3
|
||||
[cpu]
|
||||
core=dynamic
|
||||
cputype=pentium
|
||||
cycles=max
|
||||
[ne2000]
|
||||
ne2000=true
|
||||
nicbase=340
|
||||
nicirq=10
|
||||
macaddr=@@MACADDR@@
|
||||
backend=pcap
|
||||
[ethernet, pcap]
|
||||
realnic=@@REALNIC@@
|
||||
[sblaster]
|
||||
sbtype=sb16
|
||||
sbbase=220
|
||||
irq=5
|
||||
dma=1
|
||||
hdma=5
|
||||
[mixer]
|
||||
rate=44100
|
||||
blocksize=1024
|
||||
prebuffer=60
|
||||
[serial]
|
||||
serial1=directserial realport:COM1 rxpollus:100 rxburst:16
|
||||
serial2=directserial realport:COM2
|
||||
[autoexec]
|
||||
mount c "@@ROOT@@\ALPHA_1"
|
||||
mount d "@@ROOT@@\net-boot"
|
||||
d:
|
||||
echo === loading NE2000 packet-driver stack (pcap/bridge, port 340) ===
|
||||
d:\lsl
|
||||
d:\ne2000
|
||||
d:\odipkt
|
||||
c:
|
||||
cd \rel410\rp
|
||||
set VIDEOFORMAT=svga
|
||||
set BLASTER=A220 I5 D1 H5 P330 T6
|
||||
c:\sb16\diagnose /s
|
||||
set BLASTER=A240 I7 D3 H6 P300 T6
|
||||
c:\sb16\diagnose /s
|
||||
set BLASTER=A220 I5 D1 H5 P330 T6
|
||||
set TEMP=c:\
|
||||
set HEAPSIZE=15000000
|
||||
set L4GAUGE=640x480x16
|
||||
call setenv.bat r f s p
|
||||
echo === launching Red Planet via NetNub (RIO + sound; waits for console) ===
|
||||
32rtm.exe -x
|
||||
netnub -p -f rpl4opt > nn.log
|
||||
32rtm.exe -u
|
||||
echo === RP-NET-RUN-DONE ===
|
||||
pause
|
||||
@@ -0,0 +1,93 @@
|
||||
# package.ps1 -- assemble the deployable pod zip from repo sources + a fresh
|
||||
# self-contained pod-launch publish. Output: <OutDir>\<PackageName>.zip whose
|
||||
# ROOT holds postinstall.bat + the single package folder (extract to C:\games).
|
||||
# See README.md for the tree. Externally-procured pieces (Npcap, frozen renderer)
|
||||
# are bundled only if their paths are passed; otherwise they're flagged missing.
|
||||
param(
|
||||
[string]$PackageName = "TeslaPod410",
|
||||
[string]$OutDir,
|
||||
[string]$Npcap, # bundled Npcap silent installer -> deploy\npcap.exe
|
||||
[string]$Renderer, # frozen renderer exe -> renderer.exe
|
||||
[string]$VcRedist, # optional VC++ runtime -> deploy\vc_redist.x64.exe
|
||||
[switch]$NoContent, # skip ALPHA_1 + net-boot (fast structural test)
|
||||
[switch]$SkipBuild # reuse the last pod-launch publish
|
||||
)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
function Log($m) { Write-Host "[package] $m" }
|
||||
function Warn($m) { Write-Warning "[package] $m" }
|
||||
|
||||
$Repo = (Resolve-Path "$PSScriptRoot\..\..").Path
|
||||
$Emu = Join-Path $Repo 'emulator'
|
||||
if (-not $OutDir) { $OutDir = Join-Path $Emu 'dist' }
|
||||
New-Item -ItemType Directory -Force $OutDir | Out-Null
|
||||
|
||||
# --- 1. build pod-launch.exe (self-contained single-file, no runtime needed) --
|
||||
$plProj = Join-Path $Emu 'pod-launch\pod-launch.csproj'
|
||||
$plOut = Join-Path $Emu 'pod-launch\bin\pkg'
|
||||
if (-not $SkipBuild) {
|
||||
Log "publishing pod-launch (self-contained win-x64)..."
|
||||
dotnet publish $plProj -c Release -r win-x64 --self-contained true `
|
||||
-p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true `
|
||||
-o $plOut | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) { throw "dotnet publish failed" }
|
||||
}
|
||||
$podLaunch = Join-Path $plOut 'pod-launch.exe'
|
||||
if (-not (Test-Path $podLaunch)) { throw "pod-launch.exe not found at $podLaunch" }
|
||||
|
||||
# --- 2. stage the tree --------------------------------------------------------
|
||||
$stage = Join-Path $OutDir '_stage'
|
||||
if (Test-Path $stage) { Remove-Item $stage -Recurse -Force }
|
||||
$root = Join-Path $stage $PackageName
|
||||
New-Item -ItemType Directory -Force (Join-Path $root 'deploy') | Out-Null
|
||||
New-Item -ItemType Directory -Force (Join-Path $root 'roms') | Out-Null
|
||||
|
||||
# postinstall.bat -> zip ROOT (beside the package folder)
|
||||
Copy-Item (Join-Path $Emu 'deploy\postinstall.bat') $stage
|
||||
|
||||
# supervisor
|
||||
Copy-Item $podLaunch $root
|
||||
|
||||
# DOSBox-X + its DLLs
|
||||
$dbDir = Join-Path $Emu 'src\src'
|
||||
Copy-Item (Join-Path $dbDir 'dosbox-x.exe') $root
|
||||
$dlls = Get-ChildItem (Join-Path $dbDir '*.dll') -ErrorAction SilentlyContinue
|
||||
if ($dlls) { $dlls | ForEach-Object { Copy-Item $_.FullName $root } ; Log "copied $($dlls.Count) DLL(s) beside dosbox-x.exe" }
|
||||
else { Warn "no DLLs beside dosbox-x.exe -- verify the MinGW/SDL runtime DLLs the build needs are present" }
|
||||
|
||||
# conf templates + configure.ps1
|
||||
Copy-Item (Join-Path $Emu 'deploy\net_loop.conf.tmpl') $root
|
||||
Copy-Item (Join-Path $Emu 'deploy\net_rp.conf.tmpl') $root
|
||||
Copy-Item (Join-Path $Emu 'deploy\configure.ps1') (Join-Path $root 'deploy')
|
||||
|
||||
# AWE32 ROM
|
||||
Copy-Item (Join-Path $Emu 'roms\awe32.raw') (Join-Path $root 'roms')
|
||||
|
||||
# game content + packet drivers (large)
|
||||
if ($NoContent) {
|
||||
Warn "-NoContent: skipping ALPHA_1 + net-boot (structural test only, NOT installable)"
|
||||
} else {
|
||||
Log "copying ALPHA_1 game content (large)..."
|
||||
Copy-Item (Join-Path $Repo 'ALPHA_1') $root -Recurse
|
||||
Copy-Item (Join-Path $Emu 'net-boot') $root -Recurse
|
||||
}
|
||||
|
||||
# renderer (frozen exe) -- else flagged
|
||||
if ($Renderer) { Copy-Item $Renderer (Join-Path $root 'renderer.exe'); Log "bundled renderer -> renderer.exe" }
|
||||
else { Warn "no -Renderer: renderer NOT bundled (freeze pending). pod-launch needs --renderer or a bundled render-bridge at runtime." }
|
||||
|
||||
# Npcap installer -- else flagged
|
||||
if ($Npcap) { Copy-Item $Npcap (Join-Path $root 'deploy\npcap.exe'); Log "bundled Npcap -> deploy\npcap.exe" }
|
||||
else { Warn "no -Npcap: installer NOT bundled. postinstall will warn + the pcap bridge won't work until Npcap is present." }
|
||||
|
||||
if ($VcRedist) { Copy-Item $VcRedist (Join-Path $root 'deploy\vc_redist.x64.exe'); Log "bundled VC++ runtime" }
|
||||
|
||||
# --- 3. zip -------------------------------------------------------------------
|
||||
$zip = Join-Path $OutDir "$PackageName.zip"
|
||||
if (Test-Path $zip) { Remove-Item $zip -Force }
|
||||
Log "compressing -> $zip"
|
||||
Compress-Archive -Path (Join-Path $stage '*') -DestinationPath $zip
|
||||
Remove-Item $stage -Recurse -Force
|
||||
|
||||
$size = "{0:N1} MB" -f ((Get-Item $zip).Length / 1MB)
|
||||
Log "DONE: $zip ($size)"
|
||||
Log "zip root = postinstall.bat + $PackageName\ (TeslaLauncher extracts to C:\games, runs postinstall.bat elevated)"
|
||||
@@ -0,0 +1,46 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
REM ==========================================================================
|
||||
REM postinstall.bat -- runs ELEVATED after TeslaLauncher extracts the zip to
|
||||
REM the games root (C:\games). The zip root holds this file + ONE package
|
||||
REM folder; this script finds that folder, installs the bundled Npcap, and
|
||||
REM hands off to deploy\configure.ps1 for the NIC bind / IP derivation / conf
|
||||
REM rendering. Air-gapped: nothing is downloaded. See DEPLOYMENT-PLAN.md.
|
||||
REM ==========================================================================
|
||||
echo [postinstall] starting
|
||||
|
||||
REM --- locate ROOT: the single package folder beside this script -----------
|
||||
set "HERE=%~dp0"
|
||||
set "ROOT="
|
||||
for /d %%D in ("%HERE%*") do set "ROOT=%%~fD"
|
||||
if not defined ROOT (
|
||||
echo [postinstall] ERROR: no package folder found beside postinstall.bat
|
||||
exit /b 1
|
||||
)
|
||||
echo [postinstall] ROOT=!ROOT!
|
||||
|
||||
REM --- 1. Npcap silent install (bundled OEM-class installer supporting /S) --
|
||||
set "NPCAP=!ROOT!\deploy\npcap.exe"
|
||||
if exist "!NPCAP!" (
|
||||
echo [postinstall] installing Npcap silently...
|
||||
"!NPCAP!" /S
|
||||
if errorlevel 1 ( echo [postinstall] ERROR: Npcap install failed & exit /b 1 )
|
||||
) else (
|
||||
echo [postinstall] WARNING: bundled Npcap not found at "!NPCAP!"
|
||||
echo [postinstall] the pcap bridge will not work without it
|
||||
)
|
||||
|
||||
REM --- optional: bundled VC++ runtime, if present --------------------------
|
||||
set "VCREDIST=!ROOT!\deploy\vc_redist.x64.exe"
|
||||
if exist "!VCREDIST!" (
|
||||
echo [postinstall] installing VC++ runtime...
|
||||
"!VCREDIST!" /install /quiet /norestart
|
||||
)
|
||||
|
||||
REM --- 2-4. NIC bind + WATTCP my_ip=bayIP+100 + render confs (PowerShell) ---
|
||||
echo [postinstall] configuring network + rendering confs...
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "!ROOT!\deploy\configure.ps1" -Root "!ROOT!"
|
||||
if errorlevel 1 ( echo [postinstall] ERROR: configure.ps1 failed & exit /b 1 )
|
||||
|
||||
echo [postinstall] done
|
||||
exit /b 0
|
||||
Reference in New Issue
Block a user