From 5a78d35d521b123185dac138e6bdd26eea4d793d Mon Sep 17 00:00:00 2001 From: Jessica James Date: Thu, 13 May 2021 17:34:58 -0500 Subject: [PATCH] Initial commit from SVN --- build/config.json | 83 +++ build/expressions.include.RenX.SDK.txt | 53 ++ build/expressions.include.TibSun.SDK.txt | 54 ++ build/expressions.include.TibSun.txt | 7 + build/expressions.include.txt | 72 +++ build/levels.include.RenX.SDK.txt | 4 + build/levels.include.RenX.txt | 48 ++ build/levels.include.TibSun.SDK.txt | 2 + build/levels.include.TibSun.txt | 8 + build/levels.include.txt | 2 + build/scripts/Jenkinsfile | 175 +++++++ build/scripts/common.ps1 | 611 +++++++++++++++++++++++ build/shaders_last_run.txt | Bin 0 -> 14 bytes build_patch.ps1 | 72 +++ 14 files changed, 1191 insertions(+) create mode 100644 build/config.json create mode 100644 build/expressions.include.RenX.SDK.txt create mode 100644 build/expressions.include.TibSun.SDK.txt create mode 100644 build/expressions.include.TibSun.txt create mode 100644 build/expressions.include.txt create mode 100644 build/levels.include.RenX.SDK.txt create mode 100644 build/levels.include.RenX.txt create mode 100644 build/levels.include.TibSun.SDK.txt create mode 100644 build/levels.include.TibSun.txt create mode 100644 build/levels.include.txt create mode 100644 build/scripts/Jenkinsfile create mode 100644 build/scripts/common.ps1 create mode 100644 build/shaders_last_run.txt create mode 100644 build_patch.ps1 diff --git a/build/config.json b/build/config.json new file mode 100644 index 0000000..f885d3b --- /dev/null +++ b/build/config.json @@ -0,0 +1,83 @@ +{ + "branches": { + "release": { + "type": "RenX" + }, + "beta": { + "type": "RenX" + }, + "alpha": { + "type": "TibSun" + }, + "nightly": { + "type": "RenX" + }, + "nightly_ts": { + "type": "TibSun" + }, + "launcher": { + "type": "RenX" + }, + "sdk": { + "type": "RenX.SDK" + } + }, + "types": { + "RenX": { + "product": "game", + "prefix": "Patch", + "cook": true, + "retargets": [ + { + "source": "^UDKGame\\\\Content\\\\", + "target": "UDKGame\\CookedPC\\" + } + ], + "excluded_code": [ + "RA_Game", + "TibSun_Game" + ] + }, + "TibSun": { + "product": "game", + "prefix": "TSPatch", + "cook": true, + "retargets": [ + { + "source": "^UDKGame\\\\Content\\\\", + "target": "UDKGame\\CookedPC\\" + } + ], + "excluded_code": [ + "RA_Game" + ] + }, + "RenX.SDK": { + "product": "sdk", + "prefix": "SDK", + "cook": false, + "excluded_code": [ + "RA_Game", + "TibSun_Game" + ] + }, + "TibSun.SDK": { + "product": "sdk", + "prefix": "TSSDK", + "cook": false, + "excluded_code": [ + "RA_Game" + ] + } + }, + "nodes": { + "default": { + "cook_params": "-platform=pc -verbose -singlethread -auto -unattended -nopause -processes=1", + "pull_mirror": "http://us-lv.buyvm.renegade-x.com/" + }, + "win2": { + "cook_params": "-platform=pc -verbose -singlethread -auto -unattended -nopause -processes=1", + "pull_mirror": "http://10.10.10.2:8081/" + } + } +} \ No newline at end of file diff --git a/build/expressions.include.RenX.SDK.txt b/build/expressions.include.RenX.SDK.txt new file mode 100644 index 0000000..dfe0ad5 --- /dev/null +++ b/build/expressions.include.RenX.SDK.txt @@ -0,0 +1,53 @@ +# Root folder +^compile\.bat$ +^Start[A-Za-z]+\.bat$ + +# Binaries folder +^Binaries\\ActorX\\.+ +^Binaries\\FaceFXPlugins\\.+ +^Binaries\\GFx\\.+ +^Binaries\\Redist\\.+ +^Binaries\\SpeedTreeModeler\\.+ +^Binaries\\[A-Za-z\.]+\.exe$ +^Binaries\\[A-Za-z\.]+\.dll$ +^Binaries\\[A-Za-z\.]+\.config$ +^Binaries\\[A-Za-z\.]+\.xml$ + +# Development folder +^Development\\Flash\\.+ +^Development\\Src\\(?!TibSun_Game)(?!RA_Game)(?!ConsoleVariableLibrary)[A-Za-z0-9\-_]+\\.+ + +# Engine folder +^Engine\\.+ + +# ExampleAssets folder +^ExampleAssets\\.+ + +# +# UDKGame +# + +# Build +^UDKGame\\Build\\.+ + +# Content +^UDKGame\\Content\\Functions\\.+ +^UDKGame\\Content\\GFx\\.+ +^UDKGame\\Content\\RedAlert\\.+ +^UDKGame\\Content\\RenX\\.+ +^UDKGame\\Content\\Shared\\.+ +^UDKGame\\Content\\Showcases\\.+ +^UDKGame\\Content\\TestPackages\\.+ +^UDKGame\\Content\\UT3\\.+ +^UDKGame\\Content\\[A-Za-z0-9\-_]+\.bin$ +^UDKGame\\Content\\[A-Za-z0-9\-_]+\.upk$ + +# Flash +^UDKGame\\Flash\\(?!TSHUD)(?!TSPurchaseMenu).+ + +# ProjectTemplates +^UDKGame\\ProjectTemplates\\.+ + +# Script +^UDKGame\\Script\\(?!TibSun_Game)(?!RA_Game)(?!ConsoleVariableLibrary)[A-Za-z\-_]+\.u +^UDKGame\\Script\\Manifest.txt$ diff --git a/build/expressions.include.TibSun.SDK.txt b/build/expressions.include.TibSun.SDK.txt new file mode 100644 index 0000000..abcdbae --- /dev/null +++ b/build/expressions.include.TibSun.SDK.txt @@ -0,0 +1,54 @@ +# Root folder +^compile\.bat$ +^Start[A-Za-z]+\.bat$ + +# Binaries folder +^Binaries\\ActorX\\.+ +^Binaries\\FaceFXPlugins\\.+ +^Binaries\\GFx\\.+ +^Binaries\\Redist\\.+ +^Binaries\\SpeedTreeModeler\\.+ +^Binaries\\[A-Za-z\.]+\.exe$ +^Binaries\\[A-Za-z\.]+\.dll$ +^Binaries\\[A-Za-z\.]+\.config$ +^Binaries\\[A-Za-z\.]+\.xml$ + +# Development folder +^Development\\Flash\\.+ +^Development\\Src\\(?!RA_Game)(?!ConsoleVariableLibrary)[A-Za-z0-9\-_]+\\.+ + +# Engine folder +^Engine\\.+ + +# ExampleAssets folder +^ExampleAssets\\.+ + +# +# UDKGame +# + +# Build +^UDKGame\\Build\\.+ + +# Content +^UDKGame\\Content\\Functions\\.+ +^UDKGame\\Content\\GFx\\.+ +^UDKGame\\Content\\RedAlert\\.+ +^UDKGame\\Content\\RenX\\.+ +^UDKGame\\Content\\Shared\\.+ +^UDKGame\\Content\\Showcases\\.+ +^UDKGame\\Content\\TestPackages\\.+ +^UDKGame\\Content\\TiberianSun\\.+ +^UDKGame\\Content\\UT3\\.+ +^UDKGame\\Content\\[A-Za-z0-9\-_]+\.bin$ +^UDKGame\\Content\\[A-Za-z0-9\-_]+\.upk$ + +# Flash +^UDKGame\\Flash\\.+ + +# ProjectTemplates +^UDKGame\\ProjectTemplates\\.+ + +# Script +^UDKGame\\Script\\(?!RA_Game)(?!ConsoleVariableLibrary)[A-Za-z\-_]+\.u +^UDKGame\\Script\\Manifest.txt$ diff --git a/build/expressions.include.TibSun.txt b/build/expressions.include.TibSun.txt new file mode 100644 index 0000000..8866aa3 --- /dev/null +++ b/build/expressions.include.TibSun.txt @@ -0,0 +1,7 @@ +# +# CookedPC +# +^UDKGame\\CookedPC\\TiberianSun\\.+ + +# TibSun_Game.u +^UDKGame\\CookedPC\\[A-Za-z-_]+\.u diff --git a/build/expressions.include.txt b/build/expressions.include.txt new file mode 100644 index 0000000..20f6b9b --- /dev/null +++ b/build/expressions.include.txt @@ -0,0 +1,72 @@ +# +# PATCH INCLUSION LIST +# +# Each line must either be one of the following: +# 1) Entirely whitespace / empty (ignored by builds) +# 2) Start with # to indicate a comment (ignored by builds) +# 3) A regular expression to match files against, to indicate that they need to be included in the build +# + +# Binaries folder +^Binaries\\Win32\\.+ +^Binaries\\Win64\\.+ +^Binaries\\InstallData\\.+ +^Binaries\\build\.properties$ +^Binaries\\Ionic\.Zip\.Reduced\.dll$ +^Binaries\\MobileShaderAnalyzer\.exe$ +^Binaries\\MobileShaderAnalyzer\.exe\.config$ +^Binaries\\P4API\.dll$ +^Binaries\\RPCUtility\.exe$ +^Binaries\\RPCUtility\.exe\.config$ +^Binaries\\ShaderKeyTool\.exe$ +^Binaries\\ShaderKeyTool\.exe\.config$ +^Binaries\\UDKLift\.exe$ +^Binaries\\UnSetup\.exe$ +^Binaries\\UnSetup\.exe\.config$ +^Binaries\\UnSetup\.Game\.xml$ +^Binaries\\UnSetup\.Manifests\.Game\.xml$ +^Binaries\\UnSetup\.Manifests\.xml$ + +# Engine folder +^Engine\\Config\\[A-Za-z]+\.ini$ +^Engine\\Localization\\.+\\.+ +^Engine\\Shaders\\Binaries\\.+ + +# Preview videos +^PreviewVids\\Default.+ + +# +# UDKGame +# + +^UDKGame\\PCTOC.*\.txt$ + +# Cloud +^UDKGame\\Cloud\\.+ + +# Configs +^UDKGame\\Config\\Default.+\.ini$ + +# CookedPC +^UDKGame\\CookedPC\\Functions\\.+ +^UDKGame\\CookedPC\\GFx\\.+ +^UDKGame\\CookedPC\\Maps\\.+ +^UDKGame\\CookedPC\\RedAlert\\.+ +^UDKGame\\CookedPC\\RenX\\.+ +^UDKGame\\CookedPC\\Shared\\.+ +^UDKGame\\CookedPC\\UT3\\.+ +^UDKGame\\CookedPC\\[A-Za-z0-9\-_]+\.bin$ +^UDKGame\\CookedPC\\[A-Za-z0-9\-_]+\.upk$ +^UDKGame\\CookedPC\\(?!TibSun_Game)[A-Za-z-_]+\.u + +# Localization +^UDKGame\\Localization\\.+ + +# Movies +^UDKGame\\Movies\\RenX_Startup\.bik +^UDKGame\\Movies\\UDKFrontEnd.udk_loading\.bik +^UDKGame\\Movies\\UDKFrontEnd.udk_loading_HowToPlay\.bik +^UDKGame\\Movies\\UE3_logo\.bik + +# Splash +^UDKGame\\Splash\\.+ diff --git a/build/levels.include.RenX.SDK.txt b/build/levels.include.RenX.SDK.txt new file mode 100644 index 0000000..a23ea1b --- /dev/null +++ b/build/levels.include.RenX.SDK.txt @@ -0,0 +1,4 @@ +RenX-FrontEndMap +RenX-MenuMap +CNC-PTLevel +CNC-TestMap_MP diff --git a/build/levels.include.RenX.txt b/build/levels.include.RenX.txt new file mode 100644 index 0000000..c42e25e --- /dev/null +++ b/build/levels.include.RenX.txt @@ -0,0 +1,48 @@ +BH-Daybreak +BH-Field +BH-LakeSide +BH-Snow +BH-Steppe +BH-Tomb +BH-Under +BH-Walls + +CNC-Arctic_Stronghold +CNC-Canyon +CNC-CliffSide +CNC-Complex +CNC-Crash_Site +CNC-Daybreak +CNC-Desolation +CNC-Eyes +CNC-Field +CNC-Field_X +CNC-Forest +CNC-Fort +CNC-GoldRush +CNC-Hourglass +CNC-Islands +CNC-Islands_X +CNC-LakeSide +CNC-Mesa +CNC-Oasis +CNC-Outposts +CNC-Reservoir +CNC-Snow +CNC-Snow_X +CNC-Steppe +CNC-Storm +CNC-Tomb +CNC-Tunnels +CNC-Under +CNC-Uphill +CNC-Volcano +CNC-Walls +CNC-Whiteout +CNC-Xmountain + +DEF-DarkNight +DEF-LakeSide + +TDM-Caves +TDM-Deck diff --git a/build/levels.include.TibSun.SDK.txt b/build/levels.include.TibSun.SDK.txt new file mode 100644 index 0000000..93dc261 --- /dev/null +++ b/build/levels.include.TibSun.SDK.txt @@ -0,0 +1,2 @@ +RenX-FrontEndMap +RenX-MenuMap diff --git a/build/levels.include.TibSun.txt b/build/levels.include.TibSun.txt new file mode 100644 index 0000000..783745b --- /dev/null +++ b/build/levels.include.TibSun.txt @@ -0,0 +1,8 @@ +CNC-City_Flying +TS-CrashSite +TS-Pharaoh +TS-Sanctuary +TS-Hovgaard +TS-Terrace +TS-Rift +TS-Pharaoh_Small \ No newline at end of file diff --git a/build/levels.include.txt b/build/levels.include.txt new file mode 100644 index 0000000..12c8cef --- /dev/null +++ b/build/levels.include.txt @@ -0,0 +1,2 @@ +# These are levels that are included in both TibSun AND RenX builds +# Also known as: none diff --git a/build/scripts/Jenkinsfile b/build/scripts/Jenkinsfile new file mode 100644 index 0000000..d4383b0 --- /dev/null +++ b/build/scripts/Jenkinsfile @@ -0,0 +1,175 @@ +#!groovy + +def GetJobString() { + return JOB_NAME.substring(JOB_NAME.lastIndexOf('/') + 1, JOB_NAME.length()) + " #" + BUILD_NUMBER +} + +def GetBaseDiscordDescription() { + return ( + "Name: ${env.VersionName}.${env.BUILD_NUMBER}\n" + + "Branch: ${env.VersionBranch}\n" + + "Type: ${env.BuildType}\n" + + "Build: [${env.BUILD_NUMBER}](${env.BUILD_URL})\n" + ) +} + +def GetStartedDiscordDescription() { + return ( + GetBaseDiscordDescription() + ) +} + +def GetFinishedDiscordDescription() { + return ( + GetBaseDiscordDescription() + + "Status: [" + currentBuild.currentResult + "](${env.BUILD_URL})\n" + ) +} + +def GetSuccessDiscordDescription() { + return ( + GetFinishedDiscordDescription() + + "Artifacts: [changelog.txt](${env.BUILD_URL}artifact/changelog.txt), [included_files.txt](${env.BUILD_URL}artifact/included_files.txt)" + ) +} + +def GetJobDescription() { + def PatchDataName = readFile(file: 'PatchDataName.txt', encoding: 'UTF-16') + return ("Build successful. Run the \"Set Game Version\" plan to point the appropriate branch to " + PatchDataName) +} + +def SetJobDescription() { + currentBuild.description = GetJobDescription() +} + +pipeline{ + agent { + node { + label 'renx-build' + } + } + + environment { + DISCORD_WEBHOOK = credentials("f704b0eb-41e9-42d3-be14-0f951d6ef10b") + SVN_CREDS = credentials("bd2310a8-7607-4257-b749-7570e4ff2e22") + VCS_SSH_KEY = credentials("9b40a4a9-38fd-4230-bb4b-7fd29a09af85") + ROOT_DIR = "${env.workspace}" + UDK_PATH = "${ROOT_DIR}\\UDK_Uncooked" + BUILD_PATH = "${UDK_PATH}\\build" + UDK_URL = "svn://svn.renegade-x.com/svn/main/UDK_Uncooked" + } + + parameters { + choice(name: "BuildType", choices: ["Auto", "RenX", "TibSun", "RenX.SDK", "TibSun.SDK"], description: "") + choice(name: "VersionBranch", choices: ["release", "beta", "alpha", "nightly", "nightly_ts", "launcher", "sdk"], description: "Version branch to base the build on") + string(name: "VersionName", defaultValue: "", description: "Version name to assign to the build (i.e: Open Beta 5.1234)") + string(name: "RevisionNumber", defaultValue: "0", description: "SVN revision number to base the build on; leave as 0 to use most recent revision") + } + + stages { + stage("Prepare Workspace") { + // Requires: UdkPath, UdkUrl, TargetRevision, RootDir, BuildPath + steps { + discordSend description: GetStartedDiscordDescription(), footer: "Build Started", link: env.BUILD_URL, result: currentBuild.currentResult, title: ("Build Started: " + GetJobString()), webhookURL: "${env.DISCORD_WEBHOOK}" + + echo "Preparing Workspace..." + powershell ''' + # Source in common.ps1 + . "${Env:ROOT_DIR}\\common.ps1" + + # Prep the workspace + PrepRootDir "${Env:ROOT_DIR}" + + # Prep the workspace + PrepSVN "${Env:UDK_PATH}" "${Env:UDK_URL}" "${Env:RevisionNumber}" -SvnUsername ${Env:SVN_CREDS_USR} -SvnPassword ${Env:SVN_CREDS_PSW} + ''' + } + } + + stage("Build UDK") { + // Requires: BuildPath, SourceBranch, BuildType, UdkPath + steps { + echo "Building UDK..." + + powershell ''' + # Source in common.ps1 + . "${Env:ROOT_DIR}\\common.ps1" + + # Pull config data if type Auto + $BuildType = (GetBuildType "${Env:BUILD_PATH}" "${Env:VersionBranch}" -BuildType "${Env:BuildType}") + + # Build UDK + BuildUdk "${Env:UDK_PATH}" "$BuildType" + ''' + } + } + + stage("Make Patch") { + // Requires: RootDir, UdkPath, BuildType, PatchName, SourceBranch + steps { + echo "Making Patch Data..." + + powershell ''' + # Source in common.ps1 + . "${Env:ROOT_DIR}\\common.ps1" + + # Pull config data if type Auto + $BuildType = (GetBuildType "${Env:BUILD_PATH}" "${Env:VersionBranch}" -BuildType "${Env:BuildType}") + + # Make patch data + $PatchDataName = (MakePatchData "${Env:ROOT_DIR}" "${Env:UDK_PATH}" "$BuildType" "${Env:VersionName}.${Env:BUILD_NUMBER}" "${Env:VersionBranch}" -DeleteBuild) + echo "$PatchDataName" | Out-File "${Env:ROOT_DIR}\\PatchDataName.txt" -NoNewLine + ''' + } + } + + stage("Publish Patch") { + // Requires: Env:SSHKey, Env:SSHUsername, RootDir, PatchDataName + steps { + echo "Publishing Patch..." + + powershell ''' + $PatchDataName = (Get-Content "${Env:ROOT_DIR}\\PatchDataName.txt") + + # Source in common.ps1 + . "${Env:ROOT_DIR}\\common.ps1" + + # Publish patch data + PublishPatchData ${Env:VCS_SSH_KEY} ${Env:VCS_SSH_KEY_USR} "vcs.glitchware.com:/home/renx/patches/data/" "${Env:ROOT_DIR}\\$PatchDataName" + ''' + } + } + } + + post { + success { + archiveArtifacts 'included_files.txt,changelog.txt' + + echo GetJobDescription() + SetJobDescription() + discordSend description: GetSuccessDiscordDescription(), footer: GetJobDescription(), link: env.BUILD_URL, result: currentBuild.currentResult, title: GetJobString(), webhookURL: "${env.DISCORD_WEBHOOK}" + } + + failure { + discordSend description: GetFinishedDiscordDescription(), footer: "Build FAILED", link: env.BUILD_URL, result: currentBuild.currentResult, title: GetJobString(), webhookURL: "${env.DISCORD_WEBHOOK}" + } + + aborted { + discordSend description: GetFinishedDiscordDescription(), footer: "Build ABORTED", link: env.BUILD_URL, result: currentBuild.currentResult, title: GetJobString(), webhookURL: "${env.DISCORD_WEBHOOK}" + } + + cleanup { + // Cleanup build environment + powershell ''' + # Remove any lingering builds + Remove-Item "${Env:ROOT_DIR}\\Build*" -Recurse + + # Remove any lingering patch data + Remove-Item "${Env:ROOT_DIR}\\Patch*" -Recurse + Remove-Item "${Env:ROOT_DIR}\\TSPatch*" -Recurse + Remove-Item "${Env:ROOT_DIR}\\SDK*" -Recurse + Remove-Item "${Env:ROOT_DIR}\\TSSDK*" -Recurse + ''' + } + } +} diff --git a/build/scripts/common.ps1 b/build/scripts/common.ps1 new file mode 100644 index 0000000..93607a6 --- /dev/null +++ b/build/scripts/common.ps1 @@ -0,0 +1,611 @@ +function ForceDesktopSession { + $LoggedInUser = $Env:USERNAME + + # Get list of users + $UserSessions = $(quser | ForEach-Object -Process { $_ -replace '\s{2,}',',' } | ConvertFrom-CSV) + ForEach ($UserSession in $UserSessions) { + if ($UserSession.USERNAME -eq "$LoggedInUser" -or + $UserSession.USERNAME -eq ">$LoggedInUser") { + # Found our user; check if we're in a session or not + if ($UserSession.STATE -eq "Disc" -or + $UserSession.ID -eq "Disc") { + # Our session state is disconnected; open up the console + $username = $UserSession.USERNAME; + Write-Host "$LoggedInUser is disconnected; opening console" + tscon $UserSession.SESSIONNAME /dest:console + sleep 10 # Give Windows some time to init the console session + } + break + } + } +} + +function PrepRootDir { + Param( + [string]$RootDir + ) + + # Add this directory to windows defender + Write-Host "Adding Windows Defender exclusion..." + Add-MpPreference -ExclusionPath "$RootDir" +} + +function PrepSVN { + Param( + [string]$UdkPath, + [string]$UdkUrl, + [int]$TargetRevision, + [string]$SvnUsername="", + [string]$SvnPassword="" + ) + + if (![System.IO.Directory]::Exists("$UdkPath")) { + Write-Host "Checking out UDK_Uncooked..." + if (![string]::IsNullOrWhiteSpace($SvnUsername) -and + ![string]::IsNullOrWhiteSpace($SvnPassword)) { + svn checkout --non-interactive --trust-server-cert --username $SvnUsername --password $SvnPassword $UdkUrl $UdkPath + } + else { + svn checkout $UdkUrl $UdkPath + } + } + + # Revert any local changes + svn revert --recursive $UdkPath + + # Update UDK to latest revision + if ($TargetRevision -eq 0) { + svn update $UdkPath + } + else { + svn update -r $TargetRevision $UdkPath + } +} + +function GetSvnRevision { + Param( + [string]$SvnPath + ) + + return (svn info --show-item revision $SvnPath) +} + +function GetVersionData { + Param( + [string]$VersionUrl + ) + + Invoke-WebRequest "$VersionUrl" | Select-Object -ExpandProperty Content | ConvertFrom-Json +} + +function GetBranchConfig { + Param( + [string]$BuildPath, + [string]$SourceBranch + ) + + $ConfigData = (Get-Content "$BuildPath\config.json" | ConvertFrom-Json) + $ConfigBranchData = $ConfigData.branches.$SourceBranch + return $ConfigBranchData +} + +function GetTypeConfig { + Param( + [string]$BuildPath, + [string]$BuildType + ) + + $ConfigData = (Get-Content "$BuildPath\config.json" | ConvertFrom-Json) + $ConfigTypeData = $ConfigData.types.$BuildType + return $ConfigTypeData +} + +function GetNodeConfig { + Param( + [string]$BuildPath, + [string]$NodeName + ) + + $ConfigData = (Get-Content "$BuildPath\config.json" | ConvertFrom-Json) + if ([string]::IsNullOrEmpty($NodeName) -or + !$ConfigData.nodes.$NodeName) { + Write-Host "No config for $NodeName found; using default" + $NodeName = "default" + } + + $ConfigNodeData = $ConfigData.nodes.$NodeName + return $ConfigNodeData +} + +function GetBuildType { + Param( + [string]$BuildPath, + [string]$SourceBranch, + [string]$BuildType="Auto" + ) + + if ($BuildType -eq "Auto") { + $BuildType = (GetBranchConfig "$BuildPath" "$SourceBranch").type + if (!$BuildType) { + Write-Host "ERROR: Config not found for branch '$SourceBranch'" + exit 1; + } + } + + return $BuildType +} + +function OmitCodePackage { + Param( + [string]$UdkPath, + [string]$PackageName + ) + + $EngineFile = "$UdkPath\UDKGame\Config\DefaultEngineUDK.ini" + $PackageRegex = "^\+ModEditPackages=${PackageName}`$" + (Get-Content $EngineFile) -replace "$PackageRegex", "" | Set-Content $EngineFile +} + +function OmitCodePackages { + Param( + [string]$UdkPath, + [string[]]$PackageNames + ) + + foreach ($PackageName in $PackageNames) { + OmitCodePackage "$UdkPath" "$PackageName" + } +} + +function CleanupSVN { + Param( + [string]$UdkPath + ) + + # Delete unversioned files created by previous runs (logs, generated INIs) + $ChangedFilesList = (svn status --no-ignore $UdkPath) + foreach ($ChangedFileEntry in $ChangedFilesList) { + $ChangedFileName = $ChangedFileEntry.Substring(1).Trim() + # Match unversioned (?) or ignored (I) files ending with: .ini, .log, .dmp + if ($ChangedFileEntry -match "^(\?|I).+\.(ini|log|dmp)$") { + Remove-Item -Path $ChangedFileName + } + } + + # Delete CookedPC from previous runs + if ([System.IO.Directory]::Exists("$UdkPath\UDKGame\CookedPC\")) { + Write-Host "Deleting CookedPC..." + Remove-Item -Recurse -Force "$UdkPath\UDKGame\CookedPC\" + } +} + +function MakeChangelog { + Param( + [string]$UdkPath, + [int]$OldRevision, + [int]$NewRevision + ) + + svn log -v -r ${OldRevision}:${NewRevision} "$UdkPath" | Out-File changelog.txt +} + +function BuildScripts { + Param( + [string]$UdkExePath + ) + + & "$UdkExePath" make -full -buildmachine -stripsource -auto -unattended -nopause +} + +function BuildShaders { + Param( + [string]$UdkPath + ) + + # Calculate paths + $MapsRootDir = "$UdkPath\UDKGame\Content\Maps" + $UdkExePath = "$UdkPath\Binaries\Win64\UDK.exe" + $RevisionFile = "$UdkPath\build\shaders_last_run.txt" + + # Build MapsDirs + $MapsDirs = New-Object System.Collections.Generic.List[System.String] + $MapsDirs += "$MapsRootDir\RenX" + $MapsDirs += "$MapsRootDir\TiberianSun" + + # Get last revision this script ran for + $LastRevision = 0 + if ([System.IO.File]::Exists($RevisionFile)) { + $LastRevision = Get-Content $RevisionFile + } + $CurrentRevision = (GetSvnRevision $UdkPath) + + # Get list of modified files + $Files = New-Object System.Collections.Generic.List[System.String] + foreach ($MapsDir in $MapsDirs) { + $ChangedFilesList = (svn diff "-r${LastRevision}:${CurrentRevision}" --summarize "$MapsDir") + foreach ($ChangedFileEntry in $ChangedFilesList) { + $ChangedFileName = $ChangedFileEntry.Substring(1).Trim() + if ([System.IO.File]::Exists($ChangedFileName)) { + $Files += $ChangedFileName + } + } + } + + # Open each map to build shaders + foreach ($File in $Files) { + # Get package name from file + $PackageName = [System.IO.Path]::GetFileNameWithoutExtension($File) + + # Open each level with exec script to build shaders + # Note: not using 'server' for now, since it seems not to respect -EXEC, possibly because it's a "rendering" option + Write-Host "Building shaders for: $PackageName" + $Cmd = "server ${PackageName}?mutator=RenX_ExampleMutators.ShaderHelper?bIsLanMatch=true -auto -unattended -nopause" + Start-Process -Wait -FilePath "$UdkExePath" -ArgumentList "$Cmd" + } + + echo $CurrentRevision | Out-File $RevisionFile +} + +function CookGame { + Param( + [string]$UdkPath, + [string]$CookParams + ) + $UdkExePath = "$UdkPath\Binaries\Win64\UDK.com" + ForceDesktopSession + + & "$UdkExePath" CookPackages $CookParams + $CookExitCode = $LASTEXITCODE + + # Check if cook failed (exit code != 0) + if ($CookExitCode -ne 0) { + Write-Host "ERROR: Cook failed with exit code $CookExitCode" + exit 1 + } + + # Check if cook succeeded + if (Get-ChildItem "$UdkPath\UDKGame\CookedPC\Process_*") { + Write-Host "ERROR: Cook failed to complete (Process paths are still present). Exiting..." + exit 1 + } +} + +function StageCookedPC { + Param( + [string]$UdkPath, + [string]$BuildType + ) + + $CookedPCPath = "$UdkPath\UDKGame\CookedPC" + $TypedCookedPCPath = "$UdkPath\UDKGame\CookedPC_${BuildType}" + + if ([System.IO.Directory]::Exists($TypedCookedPCPath)) { + Copy-Item -Path $TypedCookedPCPath -Destination $CookedPCPath -Recurse + } +} + +function UnstageCookedPC { + Param( + [string]$UdkPath, + [string]$BuildType + ) + + $CookedPCPath = "$UdkPath\UDKGame\CookedPC" + $TypedCookedPCPath = "$UdkPath\UDKGame\CookedPC_${BuildType}" + + if ([System.IO.Directory]::Exists($CookedPCPath)) { + if ([System.IO.Directory]::Exists($TypedCookedPCPath)) { + Remove-Item -Recurse -Force "$TypedCookedPCPath" + } + + Rename-Item -Path $CookedPCPath -NewName $TypedCookedPCPath + } +} + +function BuildUdk { + Param( + [string]$UdkPath, + [string]$BuildType + ) + $UdkExePath = "$UdkPath\Binaries\Win64\UDK.com" + $BuildPath = "$UdkPath\build" + $TypeConfigData = (GetTypeConfig "$BuildPath" "$BuildType") + + # Omit private code packages where necessary + OmitCodePackages "$UdkPath" $TypeConfigData.excluded_code + + # Cleanup SVN data from previous runs + Write-Host "Cleaning up SVN from previous builds..." + CleanupSVN "$UdkPath" + + # Move in working CookedPC + Write-Host "Staging CookedPC for $BuildType build..." + StageCookedPC "$UdkPath" "$BuildType" + + # Compile scripts + Write-Host "Compiling scripts..." + BuildScripts "$UdkExePath" + + # Build shaders for all changed levels + Write-Host "Building shaders..." + BuildShaders "$UdkPath" + Write-Host "Shader build finished" + + # Cook packages + if ($TypeConfigData.cook) { + Write-Host "Cooking packages..." + $CookParams = (GetNodeConfig "$BuildPath" $Env:NODE_NAME).cook_params + CookGame "$UdkPath" "$CookParams" + } +} + +function GetIncludedFiles { + Param( + [string]$UdkPath, + [string]$BuildType + ) + $BuildPath = "$UdkPath\build" + + # Read inclusion expressions + $IncludeExpressions = (Get-Content $BuildPath\expressions.include.txt) + if ([System.IO.File]::Exists("$BuildPath\expressions.include.$BuildType.txt")) { + $IncludeExpressions += (Get-Content "$BuildPath\expressions.include.$BuildType.txt") + } + + # Read map list into inclusion expressions + $IncludeLevels = (Get-Content $BuildPath\levels.include.txt) + if ([System.IO.File]::Exists("$BuildPath\levels.include.$BuildType.txt")) { + $IncludeLevels += (Get-Content "$BuildPath\levels.include.$BuildType.txt") + } + + foreach ($LevelName in $IncludeLevels) { + if ((![string]::IsNullOrWhiteSpace($LevelName)) -and # Ignore blank lines + (!$LevelName.StartsWith("#"))) { # Ignore comments/headers + $IncludeExpressions += "^PreviewVids\\$LevelName\..+$" + $IncludeExpressions += "^UDKGame\\Config\\$LevelName.ini$" + $IncludeExpressions += "^UDKGame\\Content\\Maps\\[A-Za-z]+\\$LevelName.udk$" + $IncludeExpressions += "^UDKGame\\Movies\\LoadingScreen_$LevelName.bik$" + } + } + + # Checks if a file matches inclusion lists + function MatchesInclude { + param ( + [string]$FilePath + ) + + # Iterate over all expressions and check if FilePath matches ANY of them + foreach ($Expression in $IncludeExpressions) { + if ((![string]::IsNullOrWhiteSpace($Expression)) -and # Ignore blank lines + (!$Expression.StartsWith("#")) -and # Ignore comments/headers + ([System.IO.File]::Exists("$UdkPath\$FilePath")) -and # Ignore non-files + ($FilePath -match $Expression)) { # Check if the path matches this expression + return $true + } + } + + return $false + } + + # Compile list of files to copy from SVN + Write-Host "Scanning SVN for necessary files..." + $Files = (Get-ChildItem -Recurse $UdkPath) + $IncludedFiles = New-Object System.Collections.Generic.List[System.String] + foreach ($File in $Files) { + # Check if file matches inclusion list + $Filename = $File.FullName.Substring($UdkPath.Length + 1) + if (MatchesInclude $Filename) { + $IncludedFiles += $Filename + } + } + + echo $IncludedFiles | Out-File included_files.txt + return $IncludedFiles +} + +function GenerateBuildData { + Param( + [string]$RootDir, + [string]$UdkPath, + [string]$BuildType, + [string]$PatchName, + [string]$VersionUrl + ) + $CurrentRevision = (GetSvnRevision $UdkPath) + + Write-Host "Generating new build" + $NewBuildPath = "$RootDir\Build${CurrentRevision}" + $IncludedFiles = (GetIncludedFiles "$UdkPath" "$BuildType") + $RetargetData = (GetTypeConfig "$UdkPath\build" "$BuildType").retargets + + # Copy included files over to new build + Write-Host "Copying files from SVN..." + foreach ($Filename in $IncludedFiles) { + $SourceFilePath = "$UdkPath\$Filename" + $TargetFilePath = "$NewBuildPath\$Filename" + + # If it's from Content, copy it to CookedPC instead (i.e: Maps); note: retarget strings moved to config.json + foreach ($Retarget in $RetargetData) { + if ($Filename -match $Retarget.source) { + $TargetFilename = $Filename -replace $Retarget.source, $RetargetData.target + $TargetFilePath = "$NewBuildPath\$TargetFilename" + break + } + } + + # Create parent directories + New-Item -ItemType File -Force "$TargetFilePath" | Out-Null + Remove-Item $TargetFilePath + + # Copy file + Write-Host "Copying $Filename..." + Copy-Item -Force "$SourceFilePath" "$TargetFilePath" + } + + # Update version in INI + Write-Host "Updating version file..." + $VersionFile = "$NewBuildPath\UDKGame\Config\DefaultRenegadeX.ini" + $VersionStringRegex = '^GameVersion=".+"$' + $VersionNumberRegex = '^GameVersionNumber=.+$' + $VersionUrlRegex = '^MasterVersionURL=.+$' + (Get-Content $VersionFile) -replace $VersionStringRegex, "GameVersion=`"${PatchName}`"" | Set-Content $VersionFile + (Get-Content $VersionFile) -replace $VersionNumberRegex, "GameVersionNumber=$CurrentRevision" | Set-Content $VersionFile + (Get-Content $VersionFile) -replace $VersionUrlRegex, "MasterVersionURL=$VersionUrl" | Set-Content $VersionFile +} + +function PrepRxPatch { + Param( + [string]$RxPatchPath, + [string]$RxPatchUrl + ) + + # Checkout RXPatch if it doesn't exist + if (![System.IO.Directory]::Exists("$RxPatchPath")) { + Write-Host "Checkout RXPatch..." + svn checkout $RxPatchUrl + } + + # Enter RXPatch + svn update $RxPatchPath +} + +function PullGameBuild { + Param( + [string]$BuildUrl, + [string]$BuildPath, + [string]$RxPatchExe + ) + $PatchWorkPath = "${BuildPath}_patch_tmp" + + # Prep paths + if (![System.IO.Directory]::Exists("$BuildPath")) { + New-Item -ItemType "Directory" $BuildPath | Out-Null + } + + # Pull old build + & "$RxPatchExe" apply_web $BuildUrl $BuildPath $PatchWorkPath + + # Cleanup PatchWorkPath + Remove-Item $PatchWorkPath -Recurse -Force +} + +function GeneratePatchData { + Param( + [string]$PatchDataPath, + [string]$OldBuildPath, + [string]$NewBuildPath, + [string]$RxPatchExe + ) + + $ArgsFilePath = (New-TemporaryFile).FullName + + # Write args file + $ArgsJson = [ordered]@{ + OldPath = "$OldBuildPath" + NewPath = "$NewBuildPath" + PatchPath = "$PatchDataPath" + } + + echo $ArgsJson | ConvertTo-Json | Out-File $ArgsFilePath + + # Cleanup any old patch data + if ([System.IO.Directory]::Exists($PatchDataPath)) { + Remove-Item -Recurse -Force $PatchDataPath + } + + # Build new patch data + & "$RxPatchExe" create $ArgsFilePath + + # Cleanup args file + Remove-Item -Force $ArgsFilePath +} + +function PublishPatchData { + Param( + [string]$SSHKey, + [string]$SSHUsername, + [string]$Destination, + [string]$PatchDataPath + ) + $CurrentUsername = [Environment]::UserName + + Write-Host "Setting permissions on SSH key..." + Icacls $SSHKey /c /t /Inheritance:d # Remove Inheritance + Icacls $SSHKey /c /t /Grant "${CurrentUsername}:F" # Set Ownership to Owner + Icacls $SSHKey /c /t /Remove "Authenticated Users" BUILTIN\Administrators BUILTIN Everyone System Users # Remove All Users, except for Owner + + Write-Host "Pushing data to VCS..." + scp -i "$SSHKey" -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL -r "$PatchDataPath" "$SSHUsername@$Destination" + + # TODO: Replace this with a build step in pipeline + Write-Host "Triggering sync for mirrors..." + ssh -i "$SSHKey" -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL "$SSHUsername@vcs.glitchware.com" "/home/renx/patches/updaterepos.sh" + + Write-Host "Patch data pushed to mirrors. Deleting local data..." + Remove-Item -Recurse -Force $PatchDataPath +} + +function MakePatchData { + Param( + [string]$RootDir, + [string]$UdkPath, + [string]$BuildType, + [string]$PatchName, + [string]$SourceBranch, + [switch]$DeleteBuild + ) + $BuildPath = "$UdkPath\build" + $RxPatchPath = "$RootDir\RXPatch" + $RxPatchUrl = "svn://svn.renegade-x.com/svn/main/RXPatch" + $RxPatchExe = "$RxPatchPath\RXPatch.exe" + $CurrentRevision = (GetSvnRevision $UdkPath) + $NewBuildPath = "$RootDir\Build${CurrentRevision}" + $TypeConfig = GetTypeConfig "$BuildPath" "$BuildType" + $PatchPrefix = $TypeConfig.prefix + $ProductKey = $TypeConfig.product + $PatchDataName = "${PatchPrefix}${CurrentRevision}" + $PatchDataPath = "$RootDir\$PatchDataName" + $MirrorUrl = (GetNodeConfig "$BuildPath" $Env:NODE_NAME).pull_mirror + + # Get current version info + Write-Host "Fetching version info..." + $VersionUrl = "https://static.renegade-x.com/launcher_data/version/${SourceBranch}.json" + $VersionData = (GetVersionData "$VersionUrl") + $OldBuildNum = $VersionData.$ProductKey.version_number + $OldBuildPatchPath = $VersionData.$ProductKey.patch_path + $OldBuildUrl = "${MirrorUrl}${OldBuildPatchPath}" + $OldBuildPath = "$RootDir\Build${OldBuildNum}" + + # Compose changelog + MakeChangelog "$UdkPath" "$OldBuildNum" "$CurrentRevision" + + # Compose new build data + GenerateBuildData "$RootDir" "$UdkPath" "$BuildType" "$PatchName" "$VersionUrl" | Write-Host + UnstageCookedPC "$UdkPath" "$BuildType" + + # Prepare RXPatch for patching + PrepRxPatch "$RxPatchPath" "$RxPatchUrl" | Write-Host + + # Pull old patch data + Write-Host "Pulling previous build..." + PullGameBuild "$OldBuildUrl" "$OldBuildPath" "$RxPatchExe" | Write-Host + + # Generate patch data + Write-Host "Generating patch data" + GeneratePatchData "$PatchDataPath" "$OldBuildPath" "$NewBuildPath" "$RxPatchExe" | Write-Host + + # Cleanup build files + Remove-Item -Recurse -Force $OldBuildPath + if ($DeleteBuild) { + Remove-Item -Recurse -Force $NewBuildPath + } + + # Verify instructions.json is generated, and report failure if it's not present + if (![System.IO.File]::Exists("$PatchDataPath\instructions.json")) { + Write-Host "Patch data failed to generate" + Exit 1 + } + + Write-Host "Patch data generated successfully" + return $PatchDataName +} diff --git a/build/shaders_last_run.txt b/build/shaders_last_run.txt new file mode 100644 index 0000000000000000000000000000000000000000..90ad2e0cd82c92d15d2185b1eb67614d0a6debea GIT binary patch literal 14 TcmezW&w{~%!2k$(8Mqh#BAx=} literal 0 HcmV?d00001 diff --git a/build_patch.ps1 b/build_patch.ps1 new file mode 100644 index 0000000..c367959 --- /dev/null +++ b/build_patch.ps1 @@ -0,0 +1,72 @@ +Param( + [string]$BuildType="Auto", + [string]$SourceBranch="release", + [string]$PatchName="Open Beta 5.1234", # TODO: make non-optional + [int]$TargetRevision=0, + [switch]$Jenkins +) + +# Constants +$UdkUrl = "svn://svn.renegade-x.com/svn/main/UDK_Uncooked" +$RootDir = (Get-Location).ProviderPath +$UdkPath = "$RootDir\UDK_Uncooked" +$BuildPath = "$UdkPath\build" + +### STAGE 1: Prepare Workspace +# Requires: UdkPath, UdkUrl, TargetRevision, RootDir, BuildPath + +function PrepSVN { + Param( + [string]$UdkPath, + [string]$UdkUrl, + [int]$TargetRevision + ) + + if (![System.IO.Directory]::Exists("$UdkPath")) { + Write-Host "Checking out UDK_Uncooked..." + svn checkout $UdkUrl + } + + # Revert any local changes + svn revert --recursive $UdkPath + + # Update UDK to latest revision + if ($TargetRevision -eq 0) { + svn update $UdkPath + } + else { + svn update -r $TargetRevision $UdkPath + } +} + +# Checkout/update SVN to target revision +PrepSVN "$UdkPath" "$UdkUrl" "$TargetRevision" +. "$BuildPath\scripts\common.ps1" + +# Prepare RootDir for build +PrepRootDir "$RootDir" + +### STAGE 2: Build +# Requires: BuildPath, SourceBranch, BuildType, UdkPath + +# Pull config data if type Auto +$BuildType = (GetBuildType "$BuildPath" "$SourceBranch" -BuildType "$BuildType") + +# Build UDK +BuildUdk "$UdkPath" "$BuildType" + +### STAGE 3: Make patch +# Requires: RootDir, UdkPath, BuildType, PatchName, SourceBranch + +# Make patch data +$PatchDataName = (MakePatchData "$RootDir" "$UdkPath" "$BuildType" "$PatchName" "$SourceBranch" -DeleteBuild) +echo "PatchDataName: $PatchDataName" + +### STAGE 4: Publish patch +# Requires: Env:SSHKey, Env:SSHUsername, RootDir, PatchDataName + +# Publish patch data +if ($Jenkins) { + PublishPatchData $Env:SSHKey $Env:SSHUsername "vcs.glitchware.com:/home/renx/patches/data/" "$RootDir\$PatchDataName" + echo "Build complete. Run the `"Set Game Version`" Jenkins plan to point the appropriate branch to $PatchDataName" +}