Skip to content

Instantly share code, notes, and snippets.

@JustinGrote
Last active March 6, 2021 18:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JustinGrote/f57f021a19c2400e46fb22abcd92609a to your computer and use it in GitHub Desktop.
Save JustinGrote/f57f021a19c2400e46fb22abcd92609a to your computer and use it in GitHub Desktop.
Valheim Installation Scripts

Valheim Plus Install Script

This script was created to make installing and updating the latest version of Valheim plus as simple as possible.

Shortcut Method

To make a shortcut:

  1. Right Click Desktop -> New Shortcut

image

  1. Paste the following into the shortcut box
powershell.exe -command "iwr -useb 'git.io/ValheimPlusInstall' | iex;sleep 5"
  1. Name the shortcut whatever you want (I recommend Valheim Plus Updater)
  2. Click OK
  3. Click the shortcut. You may need to Right Click -> Run as Administrator

Command Line Method

  1. Open an admin powershel prompt on your computer:
  • Press the windows key
  • type 'powershell'
  • Type ctrl-shift-Enter to start powershell in admin mode (this is required because Valheim is typically stored in a location that requires admin access)
  1. Copy and paste the following into the window
iwr -useb 'git.io/ValheimPlusInstall' | iex
  1. Latest version of valheim plus should automatically install InstallDemo

Advanced Usage

Install to pre-existing dedicated server. It will auto-detect the dedicated server valheim-server.exe and download the correct bits

. ([scriptblock]::Create((iwr -useb 'git.io/ValheimPlusInstall'))) -Path C:\path\to\my\server
param (
#Path to the valheim root directory, for case of using an alternate installation such as a server
[String]$Path,
#Name of the release if you want to download a specific version e.g. 0.9.3
[String]$Release
)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ErrorActionPreference = 'Stop'
#region Helpers
function get-SteamInstallPath {
try {
Get-ItemPropertyValue 'HKLM:\Software\WOW6432Node\Valve\Steam' InstallPath
} catch {
throw 'Could not find Steam on your computer. Is it installed?'
}
}
function get-SteamLibraryPaths {
$libraryPaths = @()
$libraryPaths += get-steamInstallPath
$baseSteamAppsPath = Resolve-Path (Join-Path $(get-SteamInstallPath) 'steamapps')
$libraryManifest = Join-Path $baseSteamAppsPath 'libraryfolders.vdf'
if (Test-Path $libraryManifest) {
Get-Content $libraryManifest |
Where-Object { $PSItem -match '^\t\"\d+\"' } |
ConvertFrom-Csv -Delimiter "`t" -Header 'blank','index','blank2','path' |
Select-Object -Expand Path |
ForEach-Object {
$candidatePath = [Regex]::Unescape($PSItem)
if (-not (Test-Path (Join-Path $candidatePath 'steamapps'))) {
Write-Warning "Library $candidatePath was detected in $libraryManifest but we could not find it. Did you delete it? We will ignore it in the search."
} else {
$libraryPaths += $candidatePath #Warning this may not be foolproof!
}
}
}
return $libraryPaths
}
function convertFrom-SteamAppState {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline)][String]$SteamAppInfo
)
if ($steamAppInfo -notmatch '^AppState') { throw [FormatException]'This is not a steam AppState file' }
}
function get-SteamAppInstallDir ([int]$AppId) {
[String[]]$appManifestPath = foreach ($libraryPath in (get-SteamLibraryPaths)) {
$appManifestFolderPath = Join-Path $libraryPath 'steamapps'
Get-Item (Join-Path $appManifestFolderPath "appmanifest_$AppId.acf") -ErrorAction SilentlyContinue
}
if (-not $appManifestPath) { throw "Steam App with ID $AppId was not found in any of the following detected Steam libraries: $((get-SteamLibraryPaths) -join ',')" }
if ($appManifestPath.count -gt 1) { throw "Multiple installations of the app with ID $AppId were found: $($appManifestPath -join ','). This should not happen, you need to clean up your folders!" }
[String]$appFolderName = Get-Content $appManifestPath | ForEach-Object {
if ($_ -match '^\t\"installdir\"\t+\"(.+?)\"') {
return $matches[1]
}
}
if (-not $appFolderName) { throw [InvalidFormatException]"$appManifestPath does not appear to be a valid app manifest (missing or invalid installdir property)" }
$candidateAppPath = [IO.Path]::Combine(
(Split-Path $appManifestPath),
'common',
[Regex]::Unescape($appFolderName)
)
try {
return Resolve-Path $candidateAppPath
} catch {
throw "$candidateAppPath was detected as the app path for $AppId, but the actual folder was not found. Did you delete it?"
}
}
function get-GithubReleaseFileUri ([String]$user,[String]$repoName,[String]$assetName,[String]$tag) {
$releaseInfo = Invoke-RestMethod -useb "https://api.github.com/repos/$user/$repoName/releases"
if ($tag) {
$release = $releaseInfo | Where-Object tag -EQ $tag
if (-not $release) { throw "Release $tag not found in $user/$repoName" }
} else {
$release = $releaseInfo[0]
if (-not $release) { throw "No releases have been published in $user/$reponame yet" }
}
$asset = $release.assets | Where-Object name -EQ $assetName
if (-not $asset) { throw "Artifact $assetName not found in release $($release.name)" }
return $asset.browser_download_url
}
#endregion Helpers
#region Main
Write-Progress 'Detecting Valheim Directory'
$assetName = 'WindowsClient.zip'
[int]$ValheimAppId = 892970
if (-not $Path) {$Path = get-SteamAppInstallDir $ValheimAppId}
if (Test-Path (Join-Path $Path 'valheim_server.exe')) {
Write-Host -fore Cyan "Valhalla Dedicated Server detected, installing server release"
$assetName = 'WindowsServer.zip'
} else {
if (-not (Test-Path (Join-Path $Path 'valheim.exe'))) {throw "Valheim Steam Install folder detected at $Path but valheim.exe was not present. Is it corrupted or did you specify the wrong path override with -Path?"}
}
Write-Host -Fore Green "Found Valheim at $Path"
#Download latest V+ release
Write-Progress "Getting Release"
if ($Server) {$assetName = 'WindowsServer.zip'}
$releaseUri = get-GithubReleaseFileUri -User valheimPlus -repoName ValheimPlus -assetName 'WindowsClient.zip' -tag $release
Write-Progress "Downloading Release"
$tempZipPath = Join-Path ([io.path]::GetTempPath()) "$(New-Guid).zip"
try {
$configToProtect = Get-ChildItem "$Path\BepInEx\config" -Exclude '*.bak' -ErrorAction SilentlyContinue
$configToProtect.foreach{
Copy-Item $PSItem.FullName -Destination "$($PSItem.fullname).bak" -Force
}
Invoke-RestMethod -useb $releaseUri -OutFile $tempZipPath
Write-Progress "Installing to $Path"
Expand-Archive -Path $tempZipPath -DestinationPath $Path -Force
Write-Host -fore green '==========='
Write-Host -fore green "Installed Valheim Plus $assetName to $Path succsesfully!"
Write-Host -fore green "Customize your experience by editing config $Pat0\BepInEx\config\valheim_plus.cfg"
Write-Host -fore green '==========='
} catch {
throw
} finally {
$configToProtect.foreach{
Copy-Item "$($PSItem.fullname).bak" $PSItem.fullname -Force
}
Remove-Item $tempZipPath -force -ErrorAction SilentlyContinue
}
#endregion Main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment