clean up installation script, remove unnecessary big VDF parser
This commit is contained in:
parent
d63649e354
commit
ea9b5b173f
1 changed files with 76 additions and 332 deletions
408
static/install
408
static/install
|
@ -1,345 +1,89 @@
|
||||||
# VDF Deserializer
|
# Function to query the registry
|
||||||
|
function Get-RegistryValue {
|
||||||
|
param (
|
||||||
|
[string]$path,
|
||||||
|
[string]$value
|
||||||
|
)
|
||||||
|
|
||||||
Enum State
|
try {
|
||||||
{
|
$result = Get-ItemProperty -Path $path -ErrorAction Stop
|
||||||
Start = 0;
|
return $result.$value
|
||||||
Property = 1;
|
} catch {
|
||||||
Object = 2;
|
return $null
|
||||||
Conditional = 3;
|
|
||||||
Finished = 4;
|
|
||||||
Closed = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
Class VdfDeserializer
|
|
||||||
{
|
|
||||||
[PSCustomObject] Deserialize([string]$vdfContent)
|
|
||||||
{
|
|
||||||
if([string]::IsNullOrWhiteSpace($vdfContent)) {
|
|
||||||
throw 'Mandatory argument $vdfContent must be a non-empty, non-whitespace object of type [string]';
|
|
||||||
}
|
|
||||||
|
|
||||||
[System.IO.TextReader]$reader = [System.IO.StringReader]::new($vdfContent);
|
|
||||||
return $this.Deserialize($reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
[PSCustomObject] Deserialize([System.IO.TextReader]$txtReader)
|
|
||||||
{
|
|
||||||
if( !$txtReader ){
|
|
||||||
throw 'Mandatory arguments $textReader missing.';
|
|
||||||
}
|
|
||||||
|
|
||||||
$vdfReader = [VdfTextReader]::new($txtReader);
|
|
||||||
$result = [PSCustomObject]@{ };
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!$vdfReader.ReadToken())
|
|
||||||
{
|
|
||||||
throw "Incomplete VDF data.";
|
|
||||||
}
|
|
||||||
|
|
||||||
$prop = $this.ReadProperty($vdfReader);
|
|
||||||
Add-Member -InputObject $result -MemberType NoteProperty -Name $prop.Key -Value $prop.Value;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if($vdfReader)
|
|
||||||
{
|
|
||||||
$vdfReader.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
[hashtable] ReadProperty([VdfTextReader]$vdfReader)
|
|
||||||
{
|
|
||||||
$key=$vdfReader.Value;
|
|
||||||
|
|
||||||
if (!$vdfReader.ReadToken())
|
|
||||||
{
|
|
||||||
throw "Incomplete VDF data.";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($vdfReader.CurrentState -eq [State]::Property)
|
|
||||||
{
|
|
||||||
$result = @{
|
|
||||||
Key = $key;
|
|
||||||
Value = $vdfReader.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$result = @{
|
|
||||||
Key = $key;
|
|
||||||
Value = $this.ReadObject($vdfReader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
[PSCustomObject] ReadObject([VdfTextReader]$vdfReader)
|
|
||||||
{
|
|
||||||
$result = [PSCustomObject]@{ };
|
|
||||||
|
|
||||||
if (!$vdfReader.ReadToken())
|
|
||||||
{
|
|
||||||
throw "Incomplete VDF data.";
|
|
||||||
}
|
|
||||||
|
|
||||||
while ( ($vdfReader.CurrentState -ne [State]::Object) -or ($vdfReader.Value -ne "}"))
|
|
||||||
{
|
|
||||||
[hashtable]$prop = $this.ReadProperty($vdfReader);
|
|
||||||
|
|
||||||
Add-Member -InputObject $result -MemberType NoteProperty -Name $prop.Key -Value $prop.Value;
|
|
||||||
|
|
||||||
if (!$vdfReader.ReadToken())
|
|
||||||
{
|
|
||||||
throw "Incomplete VDF data.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Class VdfTextReader
|
# Get Steam installation path from registry
|
||||||
{
|
$steam_dir = Get-RegistryValue "HKLM:\SOFTWARE\Valve\Steam" "InstallPath"
|
||||||
[string]$Value;
|
|
||||||
[State]$CurrentState;
|
|
||||||
|
|
||||||
hidden [ValidateNotNull()][System.IO.TextReader]$_reader;
|
if (-not $steam_dir) {
|
||||||
|
$steam_dir = Get-RegistryValue "HKLM:\SOFTWARE\WOW6432Node\Valve\Steam" "InstallPath"
|
||||||
|
}
|
||||||
|
|
||||||
hidden [ValidateNotNull()][char[]]$_charBuffer=;
|
if (-not $steam_dir) {
|
||||||
hidden [ValidateNotNull()][char[]]$_tokenBuffer=;
|
Write-Host "Steam installation path not found"
|
||||||
|
Read-Host "Press Enter to exit"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
hidden [int32]$_charPos;
|
# Check for Garry's Mod installation
|
||||||
hidden [int32]$_charsLen;
|
$gmod_dir = Join-Path $steam_dir "steamapps\common\GarrysMod"
|
||||||
hidden [int32]$_tokensize;
|
if (-not (Test-Path (Join-Path $steam_dir "steamapps\appmanifest_4000.acf"))) {
|
||||||
hidden [bool]$_isQuoted;
|
$library_folders_path = Join-Path $steam_dir "steamapps\libraryfolders.vdf"
|
||||||
|
|
||||||
VdfTextReader([System.IO.TextReader]$txtReader)
|
if (Test-Path $library_folders_path) {
|
||||||
{
|
$lines = Get-Content $library_folders_path
|
||||||
if( !$txtReader ){
|
foreach ($line in $lines) {
|
||||||
throw "Mandatory arguments `$textReader missing.";
|
if ($line -match '^\s*"\d+"\s+"(.+)"$') {
|
||||||
}
|
$library_path = $matches[1]
|
||||||
|
if (Test-Path (Join-Path $library_path "steamapps\appmanifest_4000.acf")) {
|
||||||
$this._reader = $txtReader;
|
$gmod_dir = Join-Path $library_path "steamapps\common\GarrysMod"
|
||||||
|
break
|
||||||
$this._charBuffer=[char[]]::new(1024);
|
|
||||||
$this._tokenBuffer=[char[]]::new(4096);
|
|
||||||
|
|
||||||
$this._charPos=0;
|
|
||||||
$this._charsLen=0;
|
|
||||||
$this._tokensize=0;
|
|
||||||
$this._isQuoted=$false;
|
|
||||||
|
|
||||||
$this.Value="";
|
|
||||||
$this.CurrentState=[State]::Start;
|
|
||||||
}
|
|
||||||
|
|
||||||
[bool] ReadToken()
|
|
||||||
{
|
|
||||||
if (!$this.SeekToken())
|
|
||||||
{
|
|
||||||
return $false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this._tokenSize = 0;
|
|
||||||
|
|
||||||
while($this.EnsureBuffer())
|
|
||||||
{
|
|
||||||
[char]$curChar = $this._charBuffer[$this._charPos];
|
|
||||||
|
|
||||||
#No special treatment for escape characters
|
|
||||||
|
|
||||||
#region Quote
|
|
||||||
if ($curChar -eq '"' -or (!$this._isQuoted -and [Char]::IsWhiteSpace($curChar)))
|
|
||||||
{
|
|
||||||
$this.Value = [string]::new($this._tokenBuffer, 0, $this._tokenSize);
|
|
||||||
$this.CurrentState = [State]::Property;
|
|
||||||
$this._charPos++;
|
|
||||||
return $true;
|
|
||||||
}
|
|
||||||
#endregion Quote
|
|
||||||
|
|
||||||
#region Object Start/End
|
|
||||||
if (($curChar -eq '{') -or ($curChar -eq '}'))
|
|
||||||
{
|
|
||||||
if ($this._isQuoted)
|
|
||||||
{
|
|
||||||
$this._tokenBuffer[$this._tokenSize++] = $curChar;
|
|
||||||
$this._charPos++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
elseif ($this._tokenSize -ne 0)
|
|
||||||
{
|
|
||||||
$this.Value = [string]::new($this._tokenBuffer, 0, $this._tokenSize);
|
|
||||||
$this.CurrentState = [State]::Property;
|
|
||||||
return $true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$this.Value = $curChar.ToString();
|
|
||||||
$this.CurrentState = [State]::Object;
|
|
||||||
$this._charPos++;
|
|
||||||
return $true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion Object Start/End
|
|
||||||
|
|
||||||
#region Long Token
|
|
||||||
$this._tokenBuffer[$this._tokenSize++] = $curChar;
|
|
||||||
$this._charPos++;
|
|
||||||
#endregion Long Token
|
|
||||||
}
|
|
||||||
|
|
||||||
return $false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[void] Close()
|
|
||||||
{
|
|
||||||
$this.CurrentState = [State]::Closed;
|
|
||||||
}
|
|
||||||
|
|
||||||
hidden [bool] SeekToken()
|
|
||||||
{
|
|
||||||
while($this.EnsureBuffer())
|
|
||||||
{
|
|
||||||
# Skip Whitespace
|
|
||||||
if( [char]::IsWhiteSpace($this._charBuffer[$this._charPos]) )
|
|
||||||
{
|
|
||||||
$this._charPos++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Token
|
|
||||||
if ($this._charBuffer[$this._charPos] -eq '"')
|
|
||||||
{
|
|
||||||
$this._isQuoted = $true;
|
|
||||||
$this._charPos++;
|
|
||||||
return $true;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Comment
|
|
||||||
if ($this._charBuffer[$this._charPos] -eq '/')
|
|
||||||
{
|
|
||||||
$this.SeekNewLine();
|
|
||||||
$this._charPos++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this._isQuoted = $false;
|
|
||||||
return $true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hidden [bool] SeekNewLine()
|
|
||||||
{
|
|
||||||
while ($this.EnsureBuffer())
|
|
||||||
{
|
|
||||||
if ($this._charBuffer[++$this._charPos] == '\n')
|
|
||||||
{
|
|
||||||
return $true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hidden [bool]EnsureBuffer()
|
|
||||||
{
|
|
||||||
if($this._charPos -lt $this._charsLen -1)
|
|
||||||
{
|
|
||||||
return $true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[int32] $remainingChars = $this._charsLen - $this._charPos;
|
|
||||||
$this._charBuffer[0] = $this._charBuffer[($this._charsLen - 1) * $remainingChars]; #A bit of mathgic to improve performance by avoiding a conditional.;
|
|
||||||
$this._charsLen = $this._reader.Read($this._charBuffer, $remainingChars, 1024 - $remainingChars) + $remainingChars;
|
|
||||||
$this._charPos = 0;
|
|
||||||
|
|
||||||
return ($this._charsLen -ne 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function GetCount($thing) {
|
|
||||||
$aux = $($thing | Get-Member -MemberType NoteProperty);
|
|
||||||
$count = 0;
|
|
||||||
if ($null -eq $aux) {
|
|
||||||
$count = 0;
|
|
||||||
} elseif ( $aux -is [PSCustomObject] ) {
|
|
||||||
$count = 1;
|
|
||||||
} else {
|
|
||||||
$count = $aux.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $count;
|
|
||||||
}
|
|
||||||
|
|
||||||
$VDF = [VdfDeserializer]::new();
|
|
||||||
|
|
||||||
# Main Script
|
|
||||||
|
|
||||||
$SteamPath = Get-ItemProperty -Path HKLM:/SOFTWARE/WOW6432Node/Valve/Steam;
|
|
||||||
$SteamPath = $SteamPath.InstallPath;
|
|
||||||
$SteamPath = $SteamPath.ToString();
|
|
||||||
|
|
||||||
Write-Host Looking for Steam libraries...;
|
|
||||||
|
|
||||||
$LibraryFoldersVDF = $SteamPath + "/steamapps/libraryfolders.vdf";
|
|
||||||
$LibrariesRaw = Get-Content $LibraryFoldersVDF;
|
|
||||||
$LibrariesVDF = $VDF.Deserialize($LibrariesRaw);
|
|
||||||
|
|
||||||
Write-Host Found!;
|
|
||||||
|
|
||||||
$libcount = GetCount($LibrariesVDF.libraryfolders);
|
|
||||||
for ($i = 0; $i -lt $libcount; $i++) {
|
|
||||||
$Install = $LibrariesVDF.libraryfolders.$i;
|
|
||||||
$GMODInstalled = $Install.apps.4000;
|
|
||||||
if ($GMODInstalled) {
|
|
||||||
$GMODPath = $Install.path + "\\steamapps\\common\\GarrysMod";
|
|
||||||
$AddonsPath = $GMODPath + "\\garrysmod\\addons";
|
|
||||||
|
|
||||||
$_text = "Do you want to install in this path? It will completely wipe the previous Beatrun install if you had one! `n" + $GMODPath.replace("\\", "\") + " (y/n)";
|
|
||||||
$GMODConfirmation = Read-Host $_text;
|
|
||||||
|
|
||||||
if ($GMODConfirmation -eq "y") {
|
|
||||||
$TempPath = $GMODPath + "\\temp\\";
|
|
||||||
$ZIPPath = $TempPath + "beatrun.zip";
|
|
||||||
$FolderPath = $TempPath + "beatrun";
|
|
||||||
$FolderMainPath = $TempPath + "beatrun-main";
|
|
||||||
|
|
||||||
(New-Item -ItemType Directory -Path $TempPath) | out-null;
|
|
||||||
|
|
||||||
Write-Host Downloading the archive...;
|
|
||||||
|
|
||||||
(New-Object Net.WebClient).DownloadFile("https://github.com/JonnyBro/beatrun/archive/refs/heads/main.zip", $ZIPPath);
|
|
||||||
Write-Host Downloaded! Unpacking...;
|
|
||||||
|
|
||||||
Expand-Archive $ZIPPath $TempPath -Force;
|
|
||||||
Write-Host Unpacked successfully!;
|
|
||||||
|
|
||||||
Rename-Item $FolderMainPath $FolderPath;
|
|
||||||
Remove-Item $ZIPPath;
|
|
||||||
|
|
||||||
$confirmation = Read-Host "Do you want to install modules? (Discord + Steam Presence) (y/n)";
|
|
||||||
if ($confirmation -eq "y") {
|
|
||||||
$ModulesPath = $FolderPath + "\\lua\\*";
|
|
||||||
$NewModulesPath = $GMODPath + "\\garrysmod\\lua\\";
|
|
||||||
Copy-Item -Path $ModulesPath -Destination $NewModulesPath -Force -Recurse;
|
|
||||||
}
|
|
||||||
|
|
||||||
$AddonPath = $FolderPath + "\\beatrun";
|
|
||||||
$NewAddonPath = $AddonsPath + "\\beatrun";
|
|
||||||
if ((Test-Path $NewAddonPath) -eq $true) {
|
|
||||||
Remove-Item $NewAddonPath -Force -Recurse;
|
|
||||||
}
|
|
||||||
Move-Item -Path $AddonPath -Destination $NewAddonPath;
|
|
||||||
|
|
||||||
Remove-Item $TempPath -Force -Recurse;
|
|
||||||
|
|
||||||
Write-Host Beatrun Installed!;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path $gmod_dir)) {
|
||||||
|
Write-Host "GMod installation path not found"
|
||||||
|
Read-Host "Press Enter to exit"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "GMod installation path: $gmod_dir"
|
||||||
|
|
||||||
|
# Confirm Garry's Mod installation path
|
||||||
|
$GMODPath = Join-Path $gmod_dir "garrysmod"
|
||||||
|
$AddonsPath = Join-Path $GMODPath "addons"
|
||||||
|
$_text = "Do you want to install in this path? It will completely wipe the previous Beatrun install if you had one!`n$GMODPath (y/n)"
|
||||||
|
$GMODConfirmation = Read-Host $_text
|
||||||
|
|
||||||
|
if ($GMODConfirmation -eq "y") {
|
||||||
|
$TempPath = Join-Path $GMODPath "temp"
|
||||||
|
$ZIPPath = Join-Path $TempPath "beatrun.zip"
|
||||||
|
$FolderPath = Join-Path $TempPath "beatrun"
|
||||||
|
$FolderMainPath = Join-Path $TempPath "beatrun-main"
|
||||||
|
New-Item -ItemType Directory -Path $TempPath -Force | Out-Null
|
||||||
|
Write-Host "Downloading the archive..."
|
||||||
|
(New-Object Net.WebClient).DownloadFile("https://github.com/JonnyBro/beatrun/archive/refs/heads/main.zip", $ZIPPath)
|
||||||
|
Write-Host "Downloaded! Unpacking..."
|
||||||
|
Expand-Archive $ZIPPath $TempPath -Force
|
||||||
|
Write-Host "Unpacked successfully!"
|
||||||
|
Rename-Item $FolderMainPath $FolderPath
|
||||||
|
Remove-Item $ZIPPath
|
||||||
|
$confirmation = Read-Host "Do you want to install modules? (Discord + Steam Presence) (y/n)"
|
||||||
|
if ($confirmation -eq "y") {
|
||||||
|
$ModulesPath = Join-Path $FolderPath "lua\*"
|
||||||
|
$NewModulesPath = Join-Path $GMODPath "lua"
|
||||||
|
Copy-Item -Path $ModulesPath -Destination $NewModulesPath -Force -Recurse
|
||||||
|
}
|
||||||
|
$AddonPath = Join-Path $FolderPath "beatrun"
|
||||||
|
$NewAddonPath = Join-Path $AddonsPath "beatrun"
|
||||||
|
if (Test-Path $NewAddonPath) {
|
||||||
|
Remove-Item $NewAddonPath -Force -Recurse
|
||||||
|
}
|
||||||
|
Move-Item -Path $AddonPath -Destination $NewAddonPath
|
||||||
|
Remove-Item $TempPath -Force -Recurse
|
||||||
|
Write-Host "Beatrun Installed!"
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue