From ca56005615a50fd660241d58593a85340254aba5 Mon Sep 17 00:00:00 2001 From: Jin Hyung Ahn Date: Thu, 18 Jun 2026 01:34:59 +0900 Subject: [PATCH] build: add per-UE-version plugin packaging script + document prebuilt release zips (#53) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds tools/build-plugin.ps1: runs 'RunUAT BuildPlugin' for one UE version and zips a distributable UnrealMCPython__.zip (Binaries + Source + Content + .uplugin). Run locally once per installed UE version — the same model KawaiiPhysics uses for its per-version releases. GitHub-hosted CI can't do this (no Unreal Engine on the runner). README Step 1 now documents the two release assets: the precompiled per-version zip (no C++ toolchain needed) and the source-only zip (Unreal compiles on first open). Used to produce UnrealMCPython_5.7_2.2.0.zip, now attached to the v2.2.0 release. --- README.md | 10 ++++++-- tools/build-plugin.ps1 | 52 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 tools/build-plugin.ps1 diff --git a/README.md b/README.md index 21bfddd..6a5c2ad 100644 --- a/README.md +++ b/README.md @@ -117,12 +117,18 @@ expose, an optional C++ helper (`MCPythonHelper`) is available. Full details in **Option A: Download from GitHub Releases (Recommended)** -Download the latest zip from [Releases](https://github.com/GenOrca/unreal-mcp/releases) and extract it anywhere. Then copy `Plugins/UnrealMCPython/` into your project's `Plugins/` folder: +Each [release](https://github.com/GenOrca/unreal-mcp/releases) ships two kinds of plugin asset — pick whichever fits: + +- **`UnrealMCPython__.zip`** (e.g. `UnrealMCPython_5.7_2.2.0.zip`) — **precompiled** for that exact UE version. No C++ toolchain required; just drop it in. +- **`UnrealMCPython-v.zip`** — **source only** (the CI release pipeline runs on Linux and does not compile the C++ module). Unreal builds the module on first open, which needs a C++ toolchain. + +Extract, then copy `Plugins/UnrealMCPython/` into your project's `Plugins/` folder: ``` YourProject/ └── Plugins/ └── UnrealMCPython/ + ├── Binaries/ (precompiled zip only) ├── Source/ ├── Content/ └── UnrealMCPython.uplugin @@ -131,7 +137,7 @@ YourProject/ Keep the `mcp-server/` folder from the zip in a convenient location — you'll need its path in Step 3. > [!NOTE] -> The release zip ships the plugin as **source** (no precompiled binary — the release pipeline runs on Linux and does not build the C++ module). On first open, Unreal offers to build the `UnrealMCPython` module for you; this needs a C++ toolchain (on Windows, Visual Studio with the "Game development with C++" workload). Binaries are engine-version-specific, so source distribution keeps the plugin portable across UE versions. +> Precompiled binaries are engine-version-specific. If there's no `__` zip for your version, use the source zip and let Unreal compile it on first open (Windows: Visual Studio with the "Game development with C++" workload). Maintainers build the per-version binaries locally with `tools/build-plugin.ps1` (the CI pipeline can't — GitHub-hosted runners have no Unreal Engine). **Option B: Install from [Fab](https://fab.com/s/aed5f75d50b2)** diff --git a/tools/build-plugin.ps1 b/tools/build-plugin.ps1 new file mode 100644 index 0000000..3779a84 --- /dev/null +++ b/tools/build-plugin.ps1 @@ -0,0 +1,52 @@ +<# +.SYNOPSIS + Package UnrealMCPython as a precompiled binary plugin for one UE version, via RunUAT BuildPlugin. + +.DESCRIPTION + Produces a distributable zip (UnrealMCPython/ with Binaries + Source + Content + .uplugin) + named UnrealMCPython__.zip. Run once per UE version on a machine + that has that engine installed — the same model KawaiiPhysics uses for its per-version releases. + GitHub-hosted CI cannot do this (no Unreal Engine on the runner), so this is a local build step. + +.EXAMPLE + ./tools/build-plugin.ps1 -UeRoot "C:\Program Files\Epic Games\UE_5.7" + ./tools/build-plugin.ps1 -UeRoot "C:\Program Files\Epic Games\UE_5.8" -EngineLabel 5.8 + + Then attach the zip to a release: + gh release upload v2.2.0 .\Saved\PluginBuild\UnrealMCPython_5.7_2.2.0.zip +#> +param( + [Parameter(Mandatory = $true)][string]$UeRoot, + [string]$EngineLabel = "", + [string]$OutDir = "" +) +$ErrorActionPreference = "Stop" + +$repo = (Resolve-Path "$PSScriptRoot\..").Path +$uplugin = Join-Path $repo "Plugins\UnrealMCPython\UnrealMCPython.uplugin" +$runuat = Join-Path $UeRoot "Engine\Build\BatchFiles\RunUAT.bat" +if (-not (Test-Path $runuat)) { throw "RunUAT.bat not found at $runuat" } +if (-not (Test-Path $uplugin)) { throw ".uplugin not found at $uplugin" } +if (-not $OutDir) { $OutDir = Join-Path $repo "Saved\PluginBuild" } + +# plugin version from the .uplugin +$ver = ([regex]'"VersionName"\s*:\s*"([^"]+)"').Match((Get-Content $uplugin -Raw)).Groups[1].Value +if (-not $ver) { throw "Could not read VersionName from $uplugin" } +# engine label: explicit, else derived from the UE_x.y folder name +if (-not $EngineLabel) { $EngineLabel = (Split-Path $UeRoot -Leaf) -replace '^UE_', '' } + +$pkg = Join-Path $OutDir "UnrealMCPython" +if (Test-Path $pkg) { Remove-Item -Recurse -Force $pkg } +New-Item -ItemType Directory -Force -Path $OutDir | Out-Null + +Write-Host "Building UnrealMCPython $ver for UE $EngineLabel ..." -ForegroundColor Cyan +& $runuat BuildPlugin -Plugin="$uplugin" -Package="$pkg" -TargetPlatforms=Win64 -Rocket +if ($LASTEXITCODE -ne 0) { throw "RunUAT BuildPlugin failed (exit $LASTEXITCODE)" } + +# Intermediate is build scratch — not needed in the distributed plugin. +Remove-Item -Recurse -Force (Join-Path $pkg "Intermediate") -ErrorAction SilentlyContinue + +$zip = Join-Path $OutDir "UnrealMCPython_${EngineLabel}_${ver}.zip" +if (Test-Path $zip) { Remove-Item -Force $zip } +Compress-Archive -Path $pkg -DestinationPath $zip +Write-Host "BUILT: $zip" -ForegroundColor Green