|
<# |
|
|
|
BananaAcid 2022-2024 |
|
License MIT |
|
v1.1.0 |
|
|
|
To run this file and get PowerShellGSM installed, paste the following into your powershell 5 (not powershell 7+ [posh.exe]): |
|
|
|
|
|
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://gist.githubusercontent.com/bananaacid/1dc9117571967b26ceabc972009137ae/raw/install_PowerShellGSM.ps1')) |
|
|
|
|
|
|
|
Changes: |
|
- 14.06.2024 added version selection for PowershellGSM |
|
- 16.02.2024 fix for PalWorld config: parsed the replacement block (Sart-ServerProp) as well |
|
#> |
|
|
|
Function Main() { |
|
# Just to make sure. For me it was optional. |
|
Add-Type -Assembly System.IO.Compression.FileSystem |
|
|
|
|
|
|
|
# GIT head URL |
|
$url = "https://github.com/patrix87/PowerShellGSM/archive/refs/heads/main.zip" |
|
$tmpFile = "$env:TEMP\PowerShellGSM.main.zip"; |
|
|
|
# GIT releases JSON endpoint URL: |
|
$releasesUrl = "https://api.github.com/repos/patrix87/PowerShellGSM/releases" |
|
|
|
|
|
|
|
$lastState = Get-Content ~\.PowerShellGSM -erroraction 'silentlycontinue' | ConvertFrom-Json -erroraction 'silentlycontinue' |
|
|
|
if ( -not $? ) { |
|
$lastState = [pscustomobject]@{ |
|
exPath = ""; |
|
lastVersion = "main" |
|
} |
|
} |
|
else { |
|
## MIGRATION from v1.0.3 |
|
if ($lastState.lastVersion -eq $null) { |
|
$newState = [pscustomobject]@{ |
|
exPath = $lastState.exPath; |
|
lastVersion = "main" |
|
} |
|
$lastState = $newState |
|
} |
|
|
|
|
|
echo "Installation found in: $($lastState.exPath)" |
|
} |
|
|
|
|
|
## DOWNLOAD |
|
|
|
if (Test-Path ($tmpFile -Replace '.main.',".$($lastState.lastVersion).") ) { |
|
$r = Read-Host "Download fresh PowerShellGSM files (Y/n)" |
|
if ($r -ne "" -and $r -ne "y" -and $r -ne "Y") { |
|
$noDl = $True |
|
} |
|
} |
|
|
|
if ($noDl -ne $True) { |
|
|
|
|
|
## SELECT VERSION |
|
|
|
# get the github releases content |
|
$releases = Invoke-RestMethod -Uri $releasesUrl |
|
|
|
# prepare version selection |
|
$MenuOptions = @("cutting edge") + ($releases |% { $_.tag_name }) |
|
|
|
# ask the user to select a version |
|
$releaseVersionSelection = Create-Menu -MenuOptions $MenuOptions -Columns "auto" |
|
$releaseVersion = $MenuOptions[$releaseVersionSelection] |
|
|
|
if ($releaseVersion -eq "cutting edge" -or $releaseVersion -eq $null) { |
|
# download head as previous |
|
$releaseVersion = "main" |
|
} |
|
else { |
|
# get the url of the new |
|
$url = $releases |? { $_.tag_name -eq $releaseVersion } |% { $_.zipball_url } |
|
$tmpFile = $tmpFile -Replace '.main.',".$releaseVersion." |
|
} |
|
|
|
|
|
|
|
## DOWNLOAD |
|
|
|
echo "downloading $releaseVersion from $url" |
|
Invoke-WebRequest $url -OutFile $tmpFile |
|
|
|
# get the folder of the element |
|
$zipSubFolder = [IO.Compression.ZipFile]::OpenRead($tmpFile).Entries.FullName |? { $_ -match [regex]"patrix87-PowerShellGSM-[^\/]+\/$" } |select -first 1 |
|
|
|
|
|
## EXTRACT |
|
|
|
if ($lastState.exPath -ne "") { $def = "to " + $lastState.exPath } else { $def = "here" } |
|
|
|
$r = Read-Host "Extract installation file $def (Y/n)" |
|
if ($r -eq "" -or $r -eq "y" -or $r -eq "Y") { |
|
if ($lastState.exPath -ne "") { $r = $lastState.exPath } else { $r = pwd } |
|
} |
|
else { |
|
$r = Read-Host "Installation path" |
|
} |
|
$exPath = $r |
|
|
|
echo "Installation path used: $exPath" |
|
|
|
Expand-Archive $tmpFile $env:TEMP -Force |
|
|
|
|
|
ni $exPath -ItemType Directory -Force >$null |
|
cp "$env:TEMP\$zipSubFolder\*" $exPath\ -Force -R |
|
rm "$env:TEMP\$zipSubFolder" -Force -R |
|
|
|
$lastState.lastVersion = $releaseVersion |
|
|
|
} |
|
else { |
|
if ($lastState.exPath -ne "") { $def = $lastState.exPath } else { $def = "here" } |
|
$r = Read-Host "Enter path to previous installation (default: $def)" |
|
if ($r -eq "") { |
|
if ($lastState.exPath -ne "") { $r = $lastState.exPath } else { $r = pwd } |
|
} |
|
|
|
$exPath = $r |
|
} |
|
|
|
|
|
## ACTIVATE TEMPLATE |
|
|
|
echo "Select a server template to add:" |
|
$Options = ls $exPath\templates |? {$_.Name -notlike '#*'} |% BaseName |
|
$Selection = Create-Menu -MenuOptions $Options -Columns "auto" -MaximumColumnWidth 20 -ShowCurrentSelection $True |
|
$tmplFile = $Options[$Selection] |
|
$cfgFile = "$tmplFile.psm1" |
|
|
|
if (Test-Path $exPath\configs\$cfgFile) { |
|
$r = Read-Host "Overwrite the config file for the selected server with new and blank one (backup will be created) (y/N)" |
|
if ($r -eq "" -or $r -eq "n" -or $r -eq "N") { |
|
$ignoreReplace = $True |
|
} |
|
else { |
|
# just to make sure ... |
|
$timestamp = Get-Date -format "yyyy-MM-dd_HH-mm-ss" |
|
cp $exPath\configs\$cfgFile $exPath\configs\$cfgFile.backup.$timestamp -Force |
|
cp $exPath\launchers\$tmplFile.cmd $exPath\launchers\$tmplFile.cmd.backup.$timestamp |
|
} |
|
} |
|
|
|
if ($ignoreReplace -ne $True) { |
|
cp $exPath\templates\$cfgFile $exPath\configs -Force |
|
cp $exPath\launchers\run.cmd $exPath\launchers\$tmplFile.cmd -Force |
|
} |
|
|
|
echo "To run the selected server for $tmplFile, run $exPath\launchers\$tmplFile.cmd" |
|
|
|
|
|
## change passwords |
|
|
|
$r = Read-Host "Change all passwords in the new config (Y/n)" |
|
if ($r -eq "" -or $r -eq "y" -or $r -eq "Y") { |
|
|
|
# get content |
|
$inputFile = gc $exPath\configs\$cfgFile -Raw |
|
|
|
# find description, key, value (password) |
|
$results = [Regex]::Matches($inputFile, "^[\s]+(?<desc>#.*)*\n^[\s]+(?<line>(?<key>[^#'\s]*Password[^=\s]*)[\s]*=[\s]*""(?<val>[^""]*)"")", "IgnoreCase,Multiline") |
|
|
|
$newFile = $inputFile |
|
|
|
For ($i = 0; $i -lt $results.count; $i++) { |
|
|
|
# ask for new password and show comment + old value |
|
Write-Host "$($results[$i].Groups['desc'].Value) -- currently: '$($results[$i].Groups['val'].Value)'" -ForegroundColor DarkGray |
|
$val = Read-Host "New password for '$($results[$i].Groups['key'].Value)' (empty for random)" |
|
|
|
if ($val -eq "") { |
|
$val = ((-join (((48..57)+(65..90)+(97..122)) * 80 |Get-Random -Count 8 |%{[char]$_})) -replace '0|O|o|I|l|1|5|S|s','A').ToLower() # if not toLower, add: |Y|y|V|v|K|k|W|w|P|p|C|c|X|x |
|
Write-Host "... random: $val" |
|
} |
|
# replace old value in line |
|
$a = '"' + $results[$i].Groups["val"].Value + '"' |
|
$b = '"' + $val + '"' |
|
$x = $results[$i].Groups["line"].Value -replace $a,$b |
|
|
|
# replace old row |
|
$newFile = $newFile -replace $results[$i].Groups["line"].Value,$x |
|
} |
|
|
|
Write-Host "" |
|
|
|
# write new content |
|
$newFile | Out-File $exPath\configs\$cfgFile |
|
} |
|
|
|
|
|
## SHOW CONFIG |
|
|
|
$r = Read-Host "Show config file to be edited manually (Y/n)" |
|
if ($r -eq "" -or $r -eq "y" -or $r -eq "Y") { |
|
notepad $exPath\configs\$cfgFile |
|
explorer /select,"$exPath\configs\$cfgFile" |
|
} |
|
|
|
|
|
## SHOW FOLDER |
|
$r = Read-Host "Show installation folder (y/N)" |
|
if ($r -eq "y" -or $r -eq "Y") { |
|
explorer "$exPath" |
|
} |
|
|
|
|
|
## SHOW WEBSITE |
|
$r = Read-Host "Show PowershellGSM Readme (y/N)" |
|
if ($r -eq "y" -or $r -eq "Y") { |
|
start "https://github.com/patrix87/PowerShellGSM/blob/main/README.md" |
|
} |
|
|
|
|
|
## REMEMBER |
|
|
|
$lastState.exPath = Convert-Path $exPath |
|
ConvertTo-Json $lastState | Out-File ~\.PowerShellGSM |
|
|
|
} |
|
|
|
|
|
|
|
|
|
## MODULES |
|
|
|
|
|
# https://community.spiceworks.com/scripts/show/4785-create-menu-2-0-arrow-key-driven-powershell-menu-for-scripts |
|
# Modified by BananaAcid |
|
Function Create-Menu (){ |
|
#Start-Transcript "C:\_RRC\MenuLog.txt" |
|
Param( |
|
[Parameter(Mandatory=$True)][array]$MenuOptions, |
|
[Parameter(Mandatory=$True)][String]$Columns = "Auto", |
|
[Parameter(Mandatory=$False)][int]$MaximumColumnWidth=20, |
|
[Parameter(Mandatory=$False)][bool]$ShowCurrentSelection=$False |
|
) |
|
|
|
$consoleTop = $False; |
|
|
|
$MaxValue = $MenuOptions.count-1 |
|
$Selection = 0 |
|
$EnterPressed = $False |
|
|
|
If ($Columns -eq "Auto"){ |
|
$WindowWidth = (Get-Host).UI.RawUI.MaxWindowSize.Width |
|
$Columns = [Math]::Floor($WindowWidth/($MaximumColumnWidth+2)) |
|
} |
|
|
|
If ([int]$Columns -gt $MenuOptions.count){ |
|
$Columns = $MenuOptions.count |
|
} |
|
|
|
$RowQty = ([Math]::Ceiling(($MaxValue+1)/$Columns)) |
|
|
|
|
|
Function ClearHost () { |
|
if ($consoleTop -eq $False) { |
|
$consoleTop = [Console]::CursorTop - $RowQty |
|
} |
|
[Console]::SetCursorPosition(0, $consoleTop) |
|
} |
|
|
|
|
|
$MenuListing = @() |
|
|
|
For($i=0; $i -lt $Columns; $i++){ |
|
|
|
$ScratchArray = @() |
|
|
|
For($j=($RowQty*$i); $j -lt ($RowQty*($i+1)); $j++){ |
|
|
|
$ScratchArray += $MenuOptions[$j] |
|
} |
|
|
|
$ColWidth = ($ScratchArray |Measure-Object -Maximum -Property length).Maximum |
|
|
|
If ($ColWidth -gt $MaximumColumnWidth){ |
|
$ColWidth = $MaximumColumnWidth-1 |
|
} |
|
|
|
For($j=0; $j -lt $ScratchArray.count; $j++){ |
|
|
|
If(($ScratchArray[$j]).length -gt $($MaximumColumnWidth -2)){ |
|
$ScratchArray[$j] = $($ScratchArray[$j]).Substring(0,$($MaximumColumnWidth-4)) |
|
$ScratchArray[$j] = "$($ScratchArray[$j])..." |
|
} Else { |
|
|
|
For ($k=$ScratchArray[$j].length; $k -lt $ColWidth; $k++){ |
|
$ScratchArray[$j] = "$($ScratchArray[$j]) " |
|
} |
|
|
|
} |
|
|
|
$ScratchArray[$j] = " $($ScratchArray[$j]) " |
|
} |
|
$MenuListing += $ScratchArray |
|
} |
|
|
|
While($EnterPressed -eq $False){ |
|
|
|
If ($ShowCurrentSelection -eq $True){ |
|
$Host.UI.RawUI.WindowTitle = "CURRENT SELECTION: $($MenuOptions[$Selection])" |
|
} |
|
|
|
For ($i=0; $i -lt $RowQty; $i++){ |
|
|
|
For($j=0; $j -le (($Columns-1)*$RowQty);$j+=$RowQty){ |
|
|
|
If($j -eq (($Columns-1)*$RowQty)){ |
|
If(($i+$j) -eq $Selection){ |
|
Write-Host -BackgroundColor cyan -ForegroundColor Black "$($MenuListing[$i+$j])" |
|
} Else { |
|
Write-Host "$($MenuListing[$i+$j])" |
|
} |
|
} Else { |
|
|
|
If(($i+$j) -eq $Selection){ |
|
Write-Host -BackgroundColor Cyan -ForegroundColor Black "$($MenuListing[$i+$j])" -NoNewline |
|
} Else { |
|
Write-Host "$($MenuListing[$i+$j])" -NoNewline |
|
} |
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
#Uncomment the below line if you need to do live debugging of the current index selection. It will put it in green below the selection listing. |
|
#Write-Host -ForegroundColor Green "$Selection" |
|
|
|
$KeyInput = $host.ui.rawui.readkey("NoEcho,IncludeKeyDown").virtualkeycode |
|
|
|
Switch($KeyInput){ |
|
13{ |
|
$EnterPressed = $True |
|
Return $Selection |
|
ClearHost |
|
break |
|
} |
|
|
|
37{ #Left |
|
If ($Selection -ge $RowQty){ |
|
$Selection -= $RowQty |
|
} Else { |
|
$Selection += ($Columns-1)*$RowQty |
|
} |
|
ClearHost |
|
break |
|
} |
|
|
|
38{ #Up |
|
If ((($Selection+$RowQty)%$RowQty) -eq 0){ |
|
$Selection += $RowQty - 1 |
|
} Else { |
|
$Selection -= 1 |
|
} |
|
ClearHost |
|
break |
|
} |
|
|
|
39{ #Right |
|
If ([Math]::Ceiling($Selection/$RowQty) -eq $Columns -or ($Selection/$RowQty)+1 -eq $Columns){ |
|
$Selection -= ($Columns-1)*$RowQty |
|
} Else { |
|
$Selection += $RowQty |
|
} |
|
ClearHost |
|
break |
|
} |
|
|
|
40{ #Down |
|
If ((($Selection+1)%$RowQty) -eq 0 -or $Selection -eq $MaxValue){ |
|
$Selection = ([Math]::Floor(($Selection)/$RowQty))*$RowQty |
|
|
|
} Else { |
|
$Selection += 1 |
|
} |
|
ClearHost |
|
break |
|
} |
|
Default{ |
|
ClearHost |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
Main |
In case you get read/write/access/permission errors, create a folder like
c:\server-games
and run the installation command within that directory.