155 lines
5.5 KiB
PowerShell
155 lines
5.5 KiB
PowerShell
|
|
<#
|
||
|
|
.SYNOPSIS
|
||
|
|
symlink_models.ps1 -- place in the "Sven Co-op" root folder alongside tags.json.
|
||
|
|
|
||
|
|
.DESCRIPTION
|
||
|
|
Creates a relative symlink for every model:
|
||
|
|
svencoop_addon\models\player\<id>\<id>.mdl -> ..\..\..\..\ svencoop\models\player\helmet\helmet.mdl
|
||
|
|
|
||
|
|
Sources (pick one, or default to tags.json):
|
||
|
|
default -- model IDs from tags.json, grouped by category
|
||
|
|
-Server PATH -- scan any svencoop_addon\models\player\ directory for .mdl files
|
||
|
|
-FromFile FILE -- read one model ID per line from a text file
|
||
|
|
|
||
|
|
Dump server model IDs to a file (run on the server):
|
||
|
|
Get-ChildItem -Path "C:\path\to\svencoop_addon\models\player" -Recurse -Filter "*.mdl" |
|
||
|
|
Where-Object { $_.DirectoryName -ne "...\player" } |
|
||
|
|
ForEach-Object { $_.BaseName } | Sort-Object -Unique | Set-Content server_models.txt
|
||
|
|
|
||
|
|
.NOTES
|
||
|
|
Requires PowerShell 5.1+ and either:
|
||
|
|
- Developer Mode enabled (Settings > For developers)
|
||
|
|
- Running as Administrator
|
||
|
|
#>
|
||
|
|
[CmdletBinding()]
|
||
|
|
param(
|
||
|
|
[switch]$DryRun,
|
||
|
|
[string]$Server,
|
||
|
|
[string]$FromFile
|
||
|
|
)
|
||
|
|
|
||
|
|
Set-StrictMode -Version Latest
|
||
|
|
$ErrorActionPreference = "Stop"
|
||
|
|
|
||
|
|
# --- Paths ---
|
||
|
|
$scriptDir = $PSScriptRoot
|
||
|
|
$helmetAbs = Join-Path $scriptDir "svencoop\models\player\helmet\helmet.mdl"
|
||
|
|
$addonRoot = Join-Path $scriptDir "svencoop_addon\models\player"
|
||
|
|
$symlinkTarget = "..\..\..\..\svencoop\models\player\helmet\helmet.mdl"
|
||
|
|
|
||
|
|
# --- Pre-flight ---
|
||
|
|
if (-not (Test-Path $helmetAbs)) {
|
||
|
|
Write-Error "helmet.mdl not found: $helmetAbs`nRun from the Sven Co-op root folder."
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
|
||
|
|
[Security.Principal.WindowsBuiltInRole]::Administrator
|
||
|
|
)
|
||
|
|
if (-not $isAdmin) {
|
||
|
|
$devMode = $false
|
||
|
|
try {
|
||
|
|
$dm = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" -ErrorAction SilentlyContinue
|
||
|
|
$devMode = $dm.AllowDevelopmentWithoutDevLicense -eq 1
|
||
|
|
} catch {}
|
||
|
|
if (-not $devMode) {
|
||
|
|
Write-Warning @"
|
||
|
|
Symlink creation may fail. To fix, either:
|
||
|
|
- Enable Developer Mode (Settings > For developers > Developer Mode)
|
||
|
|
- Re-run this script as Administrator
|
||
|
|
"@
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# --- Shared: symlink one model ID ---
|
||
|
|
function Invoke-Symlink {
|
||
|
|
param([string]$ModelId)
|
||
|
|
|
||
|
|
$modelDir = Join-Path $addonRoot $ModelId
|
||
|
|
$mdlPath = Join-Path $modelDir "$ModelId.mdl"
|
||
|
|
|
||
|
|
if (-not (Test-Path $modelDir -PathType Container)) {
|
||
|
|
if (-not $DryRun) { New-Item -ItemType Directory -Path $modelDir -Force | Out-Null }
|
||
|
|
}
|
||
|
|
|
||
|
|
$item = Get-Item $mdlPath -ErrorAction SilentlyContinue
|
||
|
|
|
||
|
|
if ($item -and $item.LinkType) {
|
||
|
|
if ($item.Target -eq $symlinkTarget) { return "skipped" }
|
||
|
|
if (-not $DryRun) { Remove-Item $mdlPath -Force }
|
||
|
|
Write-Host " replace : $ModelId"
|
||
|
|
$result = "replaced"
|
||
|
|
} elseif ($item) {
|
||
|
|
if (-not $DryRun) { Remove-Item $mdlPath -Force }
|
||
|
|
Write-Host " replace : $ModelId (was real file)"
|
||
|
|
$result = "replaced"
|
||
|
|
} else {
|
||
|
|
Write-Host " create : $ModelId"
|
||
|
|
$result = "created"
|
||
|
|
}
|
||
|
|
|
||
|
|
if (-not $DryRun) {
|
||
|
|
try {
|
||
|
|
New-Item -ItemType SymbolicLink -Path $mdlPath -Target $symlinkTarget | Out-Null
|
||
|
|
} catch {
|
||
|
|
Write-Host " ERROR : $ModelId -- $_"
|
||
|
|
return "error"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return $result
|
||
|
|
}
|
||
|
|
|
||
|
|
function Write-Summary {
|
||
|
|
param([hashtable]$Counts)
|
||
|
|
$total = $Counts.created + $Counts.replaced
|
||
|
|
$prefix = if ($DryRun) { "[DRY RUN] " } else { "" }
|
||
|
|
$verb = if ($DryRun) { "would be written" } else { "written" }
|
||
|
|
$errors = if ($Counts.error) { ", $($Counts.error) errors" } else { "" }
|
||
|
|
Write-Host "`n${prefix}$total symlinks $verb ($($Counts.created) new, $($Counts.replaced) replaced), $($Counts.skipped) already correct${errors}"
|
||
|
|
}
|
||
|
|
|
||
|
|
$counts = @{ created = 0; replaced = 0; skipped = 0; error = 0 }
|
||
|
|
|
||
|
|
# --- -Server: scan a player/ directory ---
|
||
|
|
if ($Server) {
|
||
|
|
if (-not (Test-Path $Server -PathType Container)) {
|
||
|
|
Write-Error "Server path not found: $Server"
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
$modelIds = Get-ChildItem -Path $Server -Recurse -Filter "*.mdl" |
|
||
|
|
Where-Object { $_.DirectoryName -ne $Server } |
|
||
|
|
ForEach-Object { $_.BaseName } |
|
||
|
|
Sort-Object -Unique
|
||
|
|
Write-Host "`n[server] -- $($modelIds.Count) models found in $Server`n"
|
||
|
|
foreach ($id in $modelIds) { $counts[(Invoke-Symlink $id)]++ }
|
||
|
|
Write-Summary $counts
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
# --- -FromFile: read model IDs from a text file ---
|
||
|
|
if ($FromFile) {
|
||
|
|
if (-not (Test-Path $FromFile)) {
|
||
|
|
Write-Error "File not found: $FromFile"
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
$modelIds = Get-Content $FromFile | Where-Object { $_.Trim() -ne "" } | ForEach-Object { $_.Trim() }
|
||
|
|
Write-Host "`n[from file] -- $($modelIds.Count) models in $FromFile`n"
|
||
|
|
foreach ($id in $modelIds) { $counts[(Invoke-Symlink $id)]++ }
|
||
|
|
Write-Summary $counts
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
# --- Default: tags.json ---
|
||
|
|
$tagsPath = Join-Path $scriptDir "tags.json"
|
||
|
|
if (-not (Test-Path $tagsPath)) {
|
||
|
|
Write-Error "tags.json not found next to script ($tagsPath)"
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
$tags = Get-Content $tagsPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
||
|
|
foreach ($category in $tags.PSObject.Properties) {
|
||
|
|
Write-Host "`n[$($category.Name)] -- $($category.Value.Count) models"
|
||
|
|
foreach ($id in $category.Value) { $counts[(Invoke-Symlink $id)]++ }
|
||
|
|
}
|
||
|
|
Write-Summary $counts
|