@echo off rem ============================================================================ rem ETL Arena - adds our 3 Counter-Strike 1.6 servers to the TOP of your favorites rem rem What this file does, step by step (you can read all of it below): rem 1. Finds your CS 1.6 folder (Steam or non-Steam). It only looks, it changes nothing there. rem 2. Asks you to close the game, because the game rewrites the list when it closes. rem 3. Saves a backup copy of your favorites list next to it (...vdf.backup-DATE). rem 4. Puts ETL Arena Public, Mix and JailBreak first. Every other server you saved stays. rem It does not download anything, does not install anything and does not touch any rem other file. The only files it edits are the server-browser lists (*ServerBrowser*.vdf). rem ============================================================================ chcp 65001 >nul title ETL Arena - favorites powershell -NoProfile -ExecutionPolicy Bypass -Command "$s = Get-Content -LiteralPath '%~f0' -Raw -Encoding UTF8; iex $s.Substring($s.IndexOf('#' + 'POWERSHELL'))" echo. pause exit /b #POWERSHELL ---------------------------------------------------------------------- # From here on it is PowerShell (built into Windows). The batch part above only starts it. $ErrorActionPreference = 'Stop' # The servers we add. Edit nothing here unless ETL Arena moves to a new address. $EtlServers = @( @{ name = 'ETL Arena | Public'; address = '181.214.214.166:27015' }, @{ name = 'ETL Arena | Mix'; address = '181.214.214.166:27016' }, @{ name = 'ETL Arena | JailBreak'; address = '181.214.214.166:27017' } ) $EtlPrefix = '181.214.214.166:' Write-Host '' Write-Host ' ETL Arena - adding our servers to your Counter-Strike 1.6 favorites' -ForegroundColor Yellow Write-Host ' -------------------------------------------------------------------' Write-Host '' # ---------------------------------------------------------------- reading and writing .vdf files # A .vdf file is plain text: "key" "value" pairs and { } blocks. These two functions turn it into # a list we can edit and back into the same text format. function Read-Vdf([string]$text) { $script:tokens = [regex]::Matches($text, '"((?:\\.|[^"\\])*)"|[{}]') | ForEach-Object { if ($_.Value -eq '{' -or $_.Value -eq '}') { $_.Value } else { ,@($_.Groups[1].Value) } } $script:pos = 0 return Read-Block } function Read-Block { $block = [ordered]@{} while ($script:pos -lt $script:tokens.Count) { $t = $script:tokens[$script:pos]; $script:pos++ if ($t -is [string] -and $t -eq '}') { break } $key = $t[0] $next = $script:tokens[$script:pos]; $script:pos++ if ($next -is [string] -and $next -eq '{') { $block[$key] = Read-Block } else { $block[$key] = $next[0] } } return $block } function Write-Vdf($block, [int]$depth = 0) { $tabs = "`t" * $depth $out = '' foreach ($key in $block.Keys) { $value = $block[$key] if ($value -is [System.Collections.IDictionary]) { $out += "$tabs`"$key`"`r`n$tabs{`r`n" + (Write-Vdf $value ($depth + 1)) + "$tabs}`r`n" } else { $out += "$tabs`"$key`"`t`t`"$value`"`r`n" } } return $out } function Find-Key($block, [string]$name) { foreach ($k in $block.Keys) { if ($k -ieq $name) { return $k } } return $null } # ---------------------------------------------------------------- where is Counter-Strike? $games = New-Object System.Collections.Generic.List[string] function Add-Game([string]$dir) { if ($dir -and (Test-Path -LiteralPath (Join-Path $dir 'hl.exe')) -and (Test-Path -LiteralPath (Join-Path $dir 'cstrike'))) { $full = (Resolve-Path -LiteralPath $dir).Path if (-not $games.Contains($full)) { $games.Add($full) } } } # a game that is running right now Get-Process -Name hl -ErrorAction SilentlyContinue | ForEach-Object { try { Add-Game (Split-Path $_.Path) } catch {} } # Steam libraries $steam = $null try { $steam = (Get-ItemProperty 'HKCU:\Software\Valve\Steam' -ErrorAction Stop).SteamPath } catch {} if ($steam) { $steam = $steam -replace '/', '\' Add-Game (Join-Path $steam 'steamapps\common\Half-Life') $libs = Join-Path $steam 'steamapps\libraryfolders.vdf' if (Test-Path -LiteralPath $libs) { [regex]::Matches((Get-Content -LiteralPath $libs -Raw), '"path"\s+"([^"]+)"') | ForEach-Object { Add-Game (Join-Path ($_.Groups[1].Value -replace '\\\\', '\') 'steamapps\common\Half-Life') } } } # the usual places for a non-Steam install: every top folder of every drive (except Windows' # own folders), plus Desktop / Downloads / Documents, 3 folders deep. It only looks for hl.exe. $skip = 'Windows', 'ProgramData', 'System Volume Information', 'Recovery', 'PerfLogs', 'Users', '$Recycle.Bin', '$WinREAgent' $roots = @("$env:USERPROFILE\Desktop", "$env:USERPROFILE\Downloads", "$env:USERPROFILE\Documents") Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Free -ne $null } | ForEach-Object { Get-ChildItem -LiteralPath $_.Root -Directory -Force -ErrorAction SilentlyContinue | Where-Object { $skip -notcontains $_.Name } | ForEach-Object { $roots += $_.FullName } } if ($env:ETL_FAV_TEST_DIR) { $roots = @($env:ETL_FAV_TEST_DIR); $steam = $null; $games.Clear() } # only for testing on a copy foreach ($root in ($roots | Where-Object { $_ -and (Test-Path -LiteralPath $_) } | Select-Object -Unique)) { Add-Game $root Get-ChildItem -LiteralPath $root -Filter 'hl.exe' -Recurse -Depth 3 -File -ErrorAction SilentlyContinue | ForEach-Object { Add-Game $_.DirectoryName } } # which favorites files belong to each game $files = New-Object System.Collections.Generic.List[string] foreach ($g in $games) { $found = @('config\rev_ServerBrowser.vdf', 'config\ServerBrowser.vdf', 'platform\config\ServerBrowser.vdf') | ForEach-Object { Join-Path $g $_ } | Where-Object { Test-Path -LiteralPath $_ } if (-not $found) { # a fresh install has no list yet: create the one the game will read $name = if (Test-Path -LiteralPath (Join-Path $g 'rev.ini')) { 'config\rev_ServerBrowser.vdf' } else { 'config\ServerBrowser.vdf' } $found = @(Join-Path $g $name) } $found | ForEach-Object { $files.Add($_) } } # Steam keeps its favorites per Steam user if ($steam -and (Test-Path -LiteralPath (Join-Path $steam 'userdata'))) { Get-ChildItem -LiteralPath (Join-Path $steam 'userdata') -Directory -ErrorAction SilentlyContinue | ForEach-Object { $f = Join-Path $_.FullName '7\remote\serverbrowser_hist.vdf' if (Test-Path -LiteralPath $f) { $files.Add($f) } } } if ($games.Count -eq 0 -and $files.Count -eq 0) { Write-Host ' Counter-Strike 1.6 was not found on this computer.' -ForegroundColor Red Write-Host ' Add the servers by hand instead: Find Servers > Favorites > Add a Server.' return } Write-Host ' Found Counter-Strike 1.6 in:' $games | ForEach-Object { Write-Host " $_" } Write-Host '' # ---------------------------------------------------------------- the game must be closed $needSteamClosed = $files | Where-Object { $_ -like '*serverbrowser_hist.vdf' } while ($true) { $open = @() if (Get-Process -Name hl -ErrorAction SilentlyContinue) { $open += 'Counter-Strike' } if ($needSteamClosed -and (Get-Process -Name steam -ErrorAction SilentlyContinue)) { $open += 'Steam' } if (-not $open) { break } Write-Host (" Please close " + ($open -join ' and ') + ", then press Enter here.") -ForegroundColor Yellow [void](Read-Host) } # ---------------------------------------------------------------- update every favorites list $stamp = Get-Date -Format 'yyyy-MM-dd_HH-mm' $utf8 = New-Object System.Text.UTF8Encoding $false foreach ($file in $files) { $isSteam = $file -like '*serverbrowser_hist.vdf' if (Test-Path -LiteralPath $file) { Copy-Item -LiteralPath $file -Destination "$file.backup-$stamp" $root = Read-Vdf ([System.IO.File]::ReadAllText($file, $utf8)) } else { New-Item -ItemType Directory -Force -Path (Split-Path $file) | Out-Null $root = [ordered]@{} } $filtersKey = Find-Key $root 'filters' if (-not $filtersKey) { $filtersKey = if ($isSteam) { 'Filters' } else { 'filters' }; $root[$filtersKey] = [ordered]@{} } $filters = $root[$filtersKey] $favKey = Find-Key $filters 'favorites' if (-not $favKey) { $favKey = 'favorites'; $filters[$favKey] = [ordered]@{} } $old = @($filters[$favKey].Values | Where-Object { $_ -is [System.Collections.IDictionary] }) # use the same field names the existing entries use (Steam and non-Steam differ slightly) $sample = $old | Select-Object -First 1 $new = [ordered]@{} $i = 0 foreach ($s in $EtlServers) { $e = [ordered]@{} if ($sample) { foreach ($k in $sample.Keys) { switch -Regex ($k) { '^name$' { $e[$k] = $s.name } '^address$' { $e[$k] = $s.address } '^appid$' { $e[$k] = '10' } '^gamedir$' { $e[$k] = 'cstrike' } default { $e[$k] = '0' } } } } elseif ($isSteam) { $e.name = $s.name; $e.address = $s.address; $e.LastPlayed = '0'; $e.appid = '10'; $e.accountid = '0' } else { $e.name = $s.name; $e.address = $s.address; $e.lastplayed = '0'; $e.appID = '10'; $e.gamedir = 'cstrike' } $new["$i"] = $e; $i++ } # everything you had before, minus old copies of our servers foreach ($e in $old) { $addrKey = Find-Key $e 'address' if ($addrKey -and ([string]$e[$addrKey]).StartsWith($EtlPrefix)) { continue } $new["$i"] = $e; $i++ } $filters[$favKey] = $new [System.IO.File]::WriteAllText($file, (Write-Vdf $root), $utf8) Write-Host " Updated: $file" -ForegroundColor Green } Write-Host '' Write-Host ' Done! Open the game > Find Servers > Favorites. ETL Arena is at the top.' -ForegroundColor Yellow Write-Host ' A backup of your old list was saved next to each file (.backup-...).' Write-Host ' See you on the servers - etlarena.co.il'