131 lines
5.2 KiB
PowerShell
131 lines
5.2 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Collects every mod currently enabled in tModLoader (Windows) into one folder,
|
|
ready to copy into /opt/terraria/<instance>/data/ on the Linux server.
|
|
|
|
.DESCRIPTION
|
|
Output layout (mirrors the server's data/ folder):
|
|
<Out>\Mods\*.tmod
|
|
<Out>\Mods\enabled.json (only lists mods that were actually found)
|
|
<Out>\ModConfigs\*.json
|
|
|
|
.tmod files are taken from Steam's Workshop folder (all Steam libraries are
|
|
searched), falling back to Documents\My Games\Terraria\tModLoader\Mods for
|
|
mods you installed manually or built yourself.
|
|
|
|
.PARAMETER Out
|
|
Where to put the export. Default: Desktop\tmod-export
|
|
|
|
.PARAMETER TmlDir
|
|
tModLoader's save folder. Default: Documents\My Games\Terraria\tModLoader
|
|
For the preview branch use ...\My Games\Terraria\tModLoader-preview
|
|
|
|
.PARAMETER MaxVersion
|
|
Optional. Your tModLoader version as year.month (e.g. 2025.3), shown at the
|
|
bottom-left of the tModLoader main menu. Workshop builds made for a newer
|
|
tModLoader than this are skipped.
|
|
|
|
.EXAMPLE
|
|
powershell -ExecutionPolicy Bypass -File .\export-tmod-mods.ps1
|
|
powershell -ExecutionPolicy Bypass -File .\export-tmod-mods.ps1 -MaxVersion 2025.3
|
|
#>
|
|
param(
|
|
[string]$Out = (Join-Path ([Environment]::GetFolderPath('Desktop')) 'tmod-export'),
|
|
[string]$TmlDir = (Join-Path ([Environment]::GetFolderPath('MyDocuments')) 'My Games\Terraria\tModLoader'),
|
|
[version]$MaxVersion
|
|
)
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# --- Which mods are enabled? ------------------------------------------------
|
|
$enabledJson = Join-Path $TmlDir 'Mods\enabled.json'
|
|
if (-not (Test-Path $enabledJson)) {
|
|
throw "Can't find $enabledJson. Has tModLoader been run? For the preview branch pass -TmlDir ...\tModLoader-preview"
|
|
}
|
|
$enabled = @(Get-Content $enabledJson -Raw | ConvertFrom-Json)
|
|
if ($enabled.Count -eq 0) { throw "No mods are enabled in $enabledJson" }
|
|
|
|
# --- Find Steam Workshop folders for tModLoader (app 1281930) ----------------
|
|
$steamPath = (Get-ItemProperty 'HKCU:\Software\Valve\Steam' -ErrorAction SilentlyContinue).SteamPath
|
|
if (-not $steamPath) { $steamPath = 'C:\Program Files (x86)\Steam' }
|
|
$libraries = @($steamPath)
|
|
$vdf = Join-Path $steamPath 'steamapps\libraryfolders.vdf'
|
|
if (Test-Path $vdf) {
|
|
$libraries += Select-String -Path $vdf -Pattern '"path"\s+"([^"]+)"' |
|
|
ForEach-Object { $_.Matches[0].Groups[1].Value -replace '\\\\', '\' }
|
|
}
|
|
$workshopDirs = @($libraries |
|
|
ForEach-Object { Join-Path $_ 'steamapps\workshop\content\1281930' } |
|
|
Where-Object { Test-Path $_ } |
|
|
ForEach-Object { (Resolve-Path $_).Path } |
|
|
Sort-Object -Unique)
|
|
if ($workshopDirs.Count -eq 0) { Write-Warning "No Steam Workshop folder for tModLoader found; only local mods will be exported." }
|
|
|
|
function Get-FolderVersion([string]$dir) {
|
|
# Workshop items keep builds in folders named after the tModLoader version, e.g. 2024.3
|
|
$v = $null
|
|
if ([version]::TryParse((Split-Path $dir -Leaf), [ref]$v)) { return $v }
|
|
return $null
|
|
}
|
|
|
|
# --- Collect ------------------------------------------------------------------
|
|
$modsOut = Join-Path $Out 'Mods'
|
|
New-Item -ItemType Directory -Force -Path $modsOut | Out-Null
|
|
$exported = @()
|
|
$missing = @()
|
|
|
|
foreach ($mod in $enabled) {
|
|
$candidates = @()
|
|
foreach ($w in $workshopDirs) {
|
|
$candidates += @(Get-ChildItem -Path $w -Recurse -File -Filter "$mod.tmod" -ErrorAction SilentlyContinue)
|
|
}
|
|
|
|
$pick = $null
|
|
if ($candidates.Count -gt 0) {
|
|
$withVer = $candidates | ForEach-Object {
|
|
[pscustomobject]@{ File = $_; Version = (Get-FolderVersion $_.DirectoryName) }
|
|
}
|
|
# Newest version folder that isn't newer than -MaxVersion
|
|
$best = @($withVer |
|
|
Where-Object { $_.Version -and (-not $MaxVersion -or $_.Version -le $MaxVersion) } |
|
|
Sort-Object Version -Descending)
|
|
if ($best.Count -gt 0) {
|
|
$pick = $best[0].File
|
|
} else {
|
|
# Build stored at the item's top level (no version folder)
|
|
$root = @($withVer | Where-Object { -not $_.Version } |
|
|
Sort-Object { $_.File.LastWriteTime } -Descending)
|
|
if ($root.Count -gt 0) { $pick = $root[0].File }
|
|
}
|
|
}
|
|
|
|
if (-not $pick) {
|
|
$local = Join-Path $TmlDir "Mods\$mod.tmod"
|
|
if (Test-Path $local) { $pick = Get-Item $local }
|
|
}
|
|
|
|
if ($pick) {
|
|
Copy-Item $pick.FullName $modsOut -Force
|
|
$exported += $mod
|
|
Write-Host (" {0,-28} {1}" -f $mod, $pick.FullName)
|
|
} else {
|
|
$missing += $mod
|
|
Write-Warning "$mod is enabled but no .tmod file was found; skipped."
|
|
}
|
|
}
|
|
|
|
# enabled.json listing only what we exported (a missing mod would stop the server loading)
|
|
$json = ConvertTo-Json -InputObject @($exported)
|
|
[IO.File]::WriteAllText((Join-Path $modsOut 'enabled.json'), $json, (New-Object Text.UTF8Encoding $false))
|
|
|
|
# Mod settings (server-side configs matter; client-side ones are harmless)
|
|
$cfgSrc = Join-Path $TmlDir 'ModConfigs'
|
|
if (Test-Path $cfgSrc) {
|
|
$cfgOut = Join-Path $Out 'ModConfigs'
|
|
New-Item -ItemType Directory -Force -Path $cfgOut | Out-Null
|
|
Copy-Item (Join-Path $cfgSrc '*') $cfgOut -Recurse -Force
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "Exported $($exported.Count) mod(s) to $Out"
|
|
if ($missing.Count -gt 0) { Write-Warning "Missing: $($missing -join ', ')" }
|