From 5b187e1319095419f07decfd88415f43f018e3f2 Mon Sep 17 00:00:00 2001 From: Patrick Veilleux Date: Thu, 26 Aug 2021 14:11:55 -0400 Subject: [PATCH 1/8] add save feature --- .gitignore | 3 +- configs/7daystodie.psm1 | 151 +++++++++++++++++++++++++++++++ main.ps1 | 17 +++- modules/Send-RestartWarning.psm1 | 19 +++- 4 files changed, 183 insertions(+), 7 deletions(-) create mode 100644 configs/7daystodie.psm1 diff --git a/.gitignore b/.gitignore index a1c46cc..ee7083b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ backups/ logs/ tools/ -servers/ \ No newline at end of file +servers/ +configs/references/ \ No newline at end of file diff --git a/configs/7daystodie.psm1 b/configs/7daystodie.psm1 new file mode 100644 index 0000000..eea86f0 --- /dev/null +++ b/configs/7daystodie.psm1 @@ -0,0 +1,151 @@ +<# +#Change your servers settings in C:\Users\%username%\AppData\Roaming\7DaysToDie\Saves\serverconfig.xml +#> + +#--------------------------------------------------------- +# Server Configuration +#--------------------------------------------------------- +#Server Configuration +[string]$ConfigFile="$Env:userprofile\AppData\Roaming\7DaysToDie\Saves\serverconfig.xml" + +#Rcon IP, usually localhost +[string]$RconIP="127.0.0.1" + +#Rcon Port in serverconfig.xml +[int32]$RconPort=26913 + +#Rcon Password as set in serverconfig.xml +[string]$RconPassword="CHANGEME" + +#Server Log File +[string]$ServerLogFile="$Env:userprofile\AppData\Roaming\7DaysToDie\Logs\$(Get-TimeStamp).txt" + +#--------------------------------------------------------- +# Server Installation +#--------------------------------------------------------- + +#Name of the Server Instance +[string]$ServerName="7DaysToDie" + +#Server Installation Path +[string]$ServerPath=".\servers\$ServerName" + +#Steam Server App Id +[int32]$SteamAppID=294420 + +#Use Beta builds $True or $False +[bool]$Beta=$False + +#Name of the Beta Build +[string]$BetaBuild="iwillbackupmysave" + +#Beta Build Password +[string]$BetaBuildPassword="iaccepttheconsequences" + +#Process name in the task manager +[string]$ProcessName="7DaysToDieServer" + +#ProjectZomboid64.exe +[string]$ServerExec=".\servers\$ServerName\7DaysToDieServer.exe" + +#Process Priority Realtime, High, Above normal, Normal, Below normal, Low +[bool]$UsePriority=$True +[string]$AppPriority="High" + +<# +Process Affinity (Core Assignation) +Core 1=> 00000001=> 1 +Core 2=> 00000010=> 2 +Core 3=> 00000100=> 4 +Core 4=> 00001000=> 8 +Core 5=> 00010000=> 16 +Core 6=> 00100000=> 32 +Core 7=> 01000000=> 64 +Core 8=> 10000000=> 128 +========================== +8 Cores=> 11111111=> 255 +4 Cores=> 00001111=> 15 +2 Cores=> 00000011=> 3 +#> + +[bool]$UseAffinity=$False +[int32]$AppAffinity=15 + +#--------------------------------------------------------- +# Backups +#--------------------------------------------------------- + +#Do Backups +[bool]$UseBackups=$True + +#Backup Folder +[string]$BackupPath=".\backups\$ServerName" + +#Number of days of backups to keep. +[int32]$BackupDays=7 + +#Number of weeks of weekly backups to keep. +[int32]$BackupWeeks=4 + +#Folder to include in backup +[string]$ServerSaves="$Env:userprofile\AppData\Roaming\7DaysToDie" + +#--------------------------------------------------------- +# Restart Warnings (Require RCON) +#--------------------------------------------------------- +#Use Rcon to restart server softly. +[bool]$UseWarnings=$True + +#Times at which the servers will warn the players that it is about to restart. (in seconds between each timers) +[System.Collections.ArrayList]$RestartTimers=@(240,50,10) #Total wait time is 240+50+10=300 seconds or 5 minutes + +#message that will be sent. % is a wildcard for the timer. +[string]$RestartMessageMinutes="The server will restart in % minutes !" + +#message that will be sent. % is a wildcard for the timer. +[string]$RestartMessageSeconds="The server will restart in % seconds !" + +#command to send a message. +[string]$MessageCmd="say" + +#command to save the server +[string]$ServerSaveCmd="saveworld" + +#command to stop the server +[string]$ServerStopCmd="shutdown" + +#--------------------------------------------------------- +# Launch Arguments +#--------------------------------------------------------- + +#Launch Arguments +[string]$ArgumentList="-logfile $ServerLogFile -batchmode -nographics -configfile=$ConfigFile -dedicated" + +#Server Launcher +[string]$Launcher="$ServerExec" + +#--------------------------------------------------------- +# Launch Function +#--------------------------------------------------------- + +function Start-Server { + $App=Start-Process -FilePath $Launcher -WorkingDirectory $ServerPath -ArgumentList $ArgumentList -PassThru + + #Wait to see if the server is stable. + Start-Sleep -Seconds 10 + if ($App.HasExited){ + Write-Warning "Server Failed to launch." + } else { + Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server Started." + } + + # Set the priority and affinity + if ($UsePriority) { + $App.PriorityClass=$AppPriority + } + if ($UseAffinity){ + $App.ProcessorAffinity=$AppAffinity + } +} + +Export-ModuleMember -Function * -Variable * \ No newline at end of file diff --git a/main.ps1 b/main.ps1 index 49ae9fd..0539e6b 100644 --- a/main.ps1 +++ b/main.ps1 @@ -28,6 +28,21 @@ $dir=Split-Path -Path $scriptpath $dir=Resolve-Path -Path $dir Set-Location -Path $dir +#--------------------------------------------------------- +# Get server local IP +Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Getting server local IP..." +#--------------------------------------------------------- + +$ServerIP = ( + Get-NetIPConfiguration | + Where-Object { + $_.IPv4DefaultGateway -ne $null -and + $_.NetAdapter.Status -ne "Disconnected" + } +).IPv4Address.IPAddress + +Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Server local IP : $ServerIP" + #--------------------------------------------------------- # Import Functions and Modules Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Importing modules..." @@ -127,7 +142,7 @@ Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Ver #--------------------------------------------------------- If ($UseWarnings) { - Send-RestartWarning -ProcessName $ProcessName -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -RestartTimers $RestartTimers -RestartMessageMinutes $RestartMessageMinutes -RestartMessageSeconds $RestartMessageSeconds -MessageCmd $MessageCmd -ServerStopCmd $ServerStopCmd + Send-RestartWarning -ProcessName $ProcessName -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -RestartTimers $RestartTimers -RestartMessageMinutes $RestartMessageMinutes -RestartMessageSeconds $RestartMessageSeconds -MessageCmd $MessageCmd -ServerStopCmd $ServerStopCmd -ServerSaveCmd $ServerSaveCmd } else { $Server=Get-Process $ProcessName -ErrorAction SilentlyContinue $Stopped=Stop-Server -Server $Server diff --git a/modules/Send-RestartWarning.psm1 b/modules/Send-RestartWarning.psm1 index 04d8830..f90c2b5 100644 --- a/modules/Send-RestartWarning.psm1 +++ b/modules/Send-RestartWarning.psm1 @@ -22,7 +22,7 @@ function Send-Command { function Send-RestartWarning { [CmdletBinding()] param ( - [Parameter(Mandatory)] + [Parameter(Mandatory=$True)] [string]$ProcessName, [string]$Mcrcon, [string]$RconIP, @@ -32,7 +32,9 @@ function Send-RestartWarning { [string]$RestartMessageMinutes, [string]$RestartMessageSeconds, [string]$MessageCmd, - [string]$ServerStopCmd + [string]$ServerStopCmd, + [Parameter(Mandatory=$False)] + [string]$ServerSaveCmd ) $Server=Get-Process $ProcessName -ErrorAction SilentlyContinue $exited=$false @@ -40,6 +42,7 @@ function Send-RestartWarning { $Timer=$RestartTimers[0] if (!$server -or $Server.HasExited) { $exited=$true + Write-Warning "Server is not running." break } Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server is running, warning users about upcomming restart." @@ -63,11 +66,17 @@ function Send-RestartWarning { Write-Warning "Unable to send server reboot warning." break } - } - foreach ($Timer in $RestartTimers) { - } if (!$exited){ + if (![string]::IsNullOrWhiteSpace($ServerSaveCmd)){ + Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Saving server." + $Success=Send-Command -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerSaveCmd + if ($Success) { + Start-Sleep -Seconds 10 + } else { + Write-Warning "Unable to send server save command." + } + } Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Closing server." $Success=Send-Command -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerStopCmd if ($Success) { From a9c63e23a3512c4fef3f5bb513889d617d93a0cc Mon Sep 17 00:00:00 2001 From: Patrick Veilleux Date: Thu, 26 Aug 2021 14:35:56 -0400 Subject: [PATCH 2/8] Decapitalise true false, add check for fresh installation. --- configs/7daystodie.psm1 | 14 +++++++------- configs/projectzomboid.psm1 | 12 ++++++------ main.ps1 | 12 ++++++++---- modules/Backup-Server.psm1 | 4 ++-- modules/Send-RestartWarning.psm1 | 8 ++++---- modules/Stop-Server.psm1 | 4 ++-- modules/Update-Server.psm1 | 4 ++-- run.cmd | 2 +- 8 files changed, 32 insertions(+), 28 deletions(-) diff --git a/configs/7daystodie.psm1 b/configs/7daystodie.psm1 index eea86f0..cabd4e4 100644 --- a/configs/7daystodie.psm1 +++ b/configs/7daystodie.psm1 @@ -33,8 +33,8 @@ #Steam Server App Id [int32]$SteamAppID=294420 -#Use Beta builds $True or $False -[bool]$Beta=$False +#Use Beta builds $true or $false +[bool]$Beta=$false #Name of the Beta Build [string]$BetaBuild="iwillbackupmysave" @@ -49,7 +49,7 @@ [string]$ServerExec=".\servers\$ServerName\7DaysToDieServer.exe" #Process Priority Realtime, High, Above normal, Normal, Below normal, Low -[bool]$UsePriority=$True +[bool]$UsePriority=$true [string]$AppPriority="High" <# @@ -68,7 +68,7 @@ Core 8=> 10000000=> 128 2 Cores=> 00000011=> 3 #> -[bool]$UseAffinity=$False +[bool]$UseAffinity=$false [int32]$AppAffinity=15 #--------------------------------------------------------- @@ -76,7 +76,7 @@ Core 8=> 10000000=> 128 #--------------------------------------------------------- #Do Backups -[bool]$UseBackups=$True +[bool]$UseBackups=$true #Backup Folder [string]$BackupPath=".\backups\$ServerName" @@ -94,7 +94,7 @@ Core 8=> 10000000=> 128 # Restart Warnings (Require RCON) #--------------------------------------------------------- #Use Rcon to restart server softly. -[bool]$UseWarnings=$True +[bool]$UseWarnings=$true #Times at which the servers will warn the players that it is about to restart. (in seconds between each timers) [System.Collections.ArrayList]$RestartTimers=@(240,50,10) #Total wait time is 240+50+10=300 seconds or 5 minutes @@ -119,7 +119,7 @@ Core 8=> 10000000=> 128 #--------------------------------------------------------- #Launch Arguments -[string]$ArgumentList="-logfile $ServerLogFile -batchmode -nographics -configfile=$ConfigFile -dedicated" +[string]$ArgumentList="-logfile $ServerLogFile -configfile $ConfigFile -batchmode -nographics -dedicated" #Server Launcher [string]$Launcher="$ServerExec" diff --git a/configs/projectzomboid.psm1 b/configs/projectzomboid.psm1 index 6ec1037..98a78f5 100644 --- a/configs/projectzomboid.psm1 +++ b/configs/projectzomboid.psm1 @@ -56,8 +56,8 @@ You do not need to forward RCON. #Steam Server App Id [int32]$SteamAppID=380870 -#Use Beta builds $True or $False -[bool]$Beta=$False +#Use Beta builds $true or $false +[bool]$Beta=$false #Name of the Beta Build [string]$BetaBuild="iwillbackupmysave" @@ -72,7 +72,7 @@ You do not need to forward RCON. [string]$ServerExec=".\servers\$ServerName\ProjectZomboid64.exe" #Process Priority Realtime, High, Above normal, Normal, Below normal, Low -[bool]$UsePriority=$True +[bool]$UsePriority=$true [string]$AppPriority="High" <# @@ -91,7 +91,7 @@ Core 8=> 10000000=> 128 2 Cores=> 00000011=> 3 #> -[bool]$UseAffinity=$False +[bool]$UseAffinity=$false [int32]$AppAffinity=15 #--------------------------------------------------------- @@ -99,7 +99,7 @@ Core 8=> 10000000=> 128 #--------------------------------------------------------- #Do Backups -[bool]$UseBackups=$True +[bool]$UseBackups=$true #Backup Folder [string]$BackupPath=".\backups\$ServerName" @@ -117,7 +117,7 @@ Core 8=> 10000000=> 128 # Restart Warnings (Require RCON) #--------------------------------------------------------- #Use Rcon to restart server softly. -[bool]$UseWarnings=$True +[bool]$UseWarnings=$true #Times at which the servers will warn the players that it is about to restart. (in seconds between each timers) [System.Collections.ArrayList]$RestartTimers=@(240,50,10) #Total wait time is 240+50+10=300 seconds or 5 minutes diff --git a/main.ps1 b/main.ps1 index 0539e6b..5e480ef 100644 --- a/main.ps1 +++ b/main.ps1 @@ -130,10 +130,12 @@ if ($MissingDependencies.Count -gt 0){ Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Verifying Server installation..." #--------------------------------------------------------- +[string]$FreshInstall=$false if (!(Test-Path $ServerExec)){ Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server is not installed : Installing $ServerName Server." Update-Server -ServerPath $ServerPath -SteamCMD $SteamCMD -SteamAppID $SteamAppID -Beta $Beta -BetaBuild $BetaBuild -BetaBuildPassword $BetaBuildPassword -UpdateType "Installing" Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server successfully installed." + $FreshInstall=$true } #--------------------------------------------------------- @@ -141,7 +143,7 @@ if (!(Test-Path $ServerExec)){ Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Verifying Server State..." #--------------------------------------------------------- -If ($UseWarnings) { +If ($UseWarnings -and !$FreshInstall) { Send-RestartWarning -ProcessName $ProcessName -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -RestartTimers $RestartTimers -RestartMessageMinutes $RestartMessageMinutes -RestartMessageSeconds $RestartMessageSeconds -MessageCmd $MessageCmd -ServerStopCmd $ServerStopCmd -ServerSaveCmd $ServerSaveCmd } else { $Server=Get-Process $ProcessName -ErrorAction SilentlyContinue @@ -158,7 +160,7 @@ If ($UseWarnings) { Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Verifying Backups..." #--------------------------------------------------------- -if ($UseBackups) { +if ($UseBackups -and !$FreshInstall) { Backup-Server -BackupPath $BackupPath -ServerSaves $ServerSaves -SevenZip $SevenZip -BackupDays $BackupDays -BackupWeeks $BackupWeeks } @@ -167,8 +169,10 @@ if ($UseBackups) { Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Updating Server..." #--------------------------------------------------------- -Update-Server -ServerPath $ServerPath -SteamCMD $SteamCMD -SteamAppID $SteamAppID -Beta $Beta -BetaBuild $BetaBuild -BetaBuildPassword $BetaBuildPassword -UpdateType "Updating" -Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server successfully updated and/or verified." +if (!$FreshInstall) { + Update-Server -ServerPath $ServerPath -SteamCMD $SteamCMD -SteamAppID $SteamAppID -Beta $Beta -BetaBuild $BetaBuild -BetaBuildPassword $BetaBuildPassword -UpdateType "Updating" + Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server successfully updated and/or verified." +} #--------------------------------------------------------- # Start Server diff --git a/modules/Backup-Server.psm1 b/modules/Backup-Server.psm1 index f08c5c9..30ddd7b 100644 --- a/modules/Backup-Server.psm1 +++ b/modules/Backup-Server.psm1 @@ -1,11 +1,11 @@ function Backup-Server { [CmdletBinding()] param ( - [Parameter(Mandatory=$True)] + [Parameter(Mandatory=$true)] [string]$BackupPath, [string]$ServerSaves, [string]$SevenZip, - [Parameter(Mandatory=$False)] + [Parameter(Mandatory=$false)] [int32]$BackupDays=7, [int32]$BackupWeeks=4 ) diff --git a/modules/Send-RestartWarning.psm1 b/modules/Send-RestartWarning.psm1 index f90c2b5..8720ad1 100644 --- a/modules/Send-RestartWarning.psm1 +++ b/modules/Send-RestartWarning.psm1 @@ -12,17 +12,17 @@ function Send-Command { $Task=Start-Process $Mcrcon -ArgumentList "-c -H $RconIP -P $RconPort -p $RconPassword `"$Command`"" -Wait -PassThru -NoNewWindow if ($Task.ExitCode -eq 0) { Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Command Sent." - return $True + return $true } else { Write-Warning "Unable to send command" - return $False + return $false } } function Send-RestartWarning { [CmdletBinding()] param ( - [Parameter(Mandatory=$True)] + [Parameter(Mandatory=$true)] [string]$ProcessName, [string]$Mcrcon, [string]$RconIP, @@ -33,7 +33,7 @@ function Send-RestartWarning { [string]$RestartMessageSeconds, [string]$MessageCmd, [string]$ServerStopCmd, - [Parameter(Mandatory=$False)] + [Parameter(Mandatory=$false)] [string]$ServerSaveCmd ) $Server=Get-Process $ProcessName -ErrorAction SilentlyContinue diff --git a/modules/Stop-Server.psm1 b/modules/Stop-Server.psm1 index 9f55cce..9dac310 100644 --- a/modules/Stop-Server.psm1 +++ b/modules/Stop-Server.psm1 @@ -25,9 +25,9 @@ function Stop-Server { } Start-Sleep -Seconds 10 if ($Server.HasExited) { - return $True + return $true } else { - return $False + return $false } } Export-ModuleMember -Function Stop-Server \ No newline at end of file diff --git a/modules/Update-Server.psm1 b/modules/Update-Server.psm1 index 65947ec..11059a4 100644 --- a/modules/Update-Server.psm1 +++ b/modules/Update-Server.psm1 @@ -1,13 +1,13 @@ function Update-Server { [CmdletBinding()] param ( - [Parameter(Mandatory=$True)] + [Parameter(Mandatory=$true)] [string]$ServerPath, [string]$SteamCMD, [int32]$SteamAppID, [boolean]$Beta, - [Parameter(Mandatory=$False)] + [Parameter(Mandatory=$false)] [string]$BetaBuild, [string]$BetaBuildPassword, [string]$UpdateType diff --git a/run.cmd b/run.cmd index a644f5f..66696b7 100644 --- a/run.cmd +++ b/run.cmd @@ -1 +1 @@ -start powershell.exe -noprofile -executionpolicy bypass -file ".\main.ps1" -ServerCfg "projectzomboid" \ No newline at end of file +start powershell.exe -noprofile -executionpolicy bypass -file ".\main.ps1" -ServerCfg "7daystodie" \ No newline at end of file From af744de5b965d5bf6beb13d9ab50a36119f8890c Mon Sep 17 00:00:00 2001 From: Patrick Veilleux Date: Thu, 26 Aug 2021 20:58:50 -0400 Subject: [PATCH 3/8] add Telnet Support --- configs/7daystodie.psm1 | 16 ++++++--- main.ps1 | 10 +++--- modules/Get-Telnet.psm1 | 61 ++++++++++++++++++++++++++++++++ modules/Send-RestartWarning.psm1 | 54 +++++++++++++++++++++++----- modules/Stop-Server.psm1 | 8 ++--- 5 files changed, 128 insertions(+), 21 deletions(-) create mode 100644 modules/Get-Telnet.psm1 diff --git a/configs/7daystodie.psm1 b/configs/7daystodie.psm1 index cabd4e4..35219ab 100644 --- a/configs/7daystodie.psm1 +++ b/configs/7daystodie.psm1 @@ -12,10 +12,10 @@ [string]$RconIP="127.0.0.1" #Rcon Port in serverconfig.xml -[int32]$RconPort=26913 +[int32]$RconPort=8081 #Rcon Password as set in serverconfig.xml -[string]$RconPassword="CHANGEME" +[string]$RconPassword="" #Server Log File [string]$ServerLogFile="$Env:userprofile\AppData\Roaming\7DaysToDie\Logs\$(Get-TimeStamp).txt" @@ -96,6 +96,9 @@ Core 8=> 10000000=> 128 #Use Rcon to restart server softly. [bool]$UseWarnings=$true +#Use Telnet protocol instead of RCON +[string]$protocol="Telnet" + #Times at which the servers will warn the players that it is about to restart. (in seconds between each timers) [System.Collections.ArrayList]$RestartTimers=@(240,50,10) #Total wait time is 240+50+10=300 seconds or 5 minutes @@ -119,16 +122,21 @@ Core 8=> 10000000=> 128 #--------------------------------------------------------- #Launch Arguments -[string]$ArgumentList="-logfile $ServerLogFile -configfile $ConfigFile -batchmode -nographics -dedicated" +[string]$ArgumentList="-logfile $ServerLogFile -configfile=$ConfigFile -batchmode -nographics -dedicated -quit" #Server Launcher -[string]$Launcher="$ServerExec" +[string]$Launcher=$ServerExec #--------------------------------------------------------- # Launch Function #--------------------------------------------------------- function Start-Server { + #Copy Config File if not created. Do not modify the one in the server directory, it will be overwriten on updates. + If(-Not (Test-Path -Path $ConfigFile -PathType "leaf")){ + Copy-Item -Path "$ServerPath\serverconfig.xml" -Destination $ConfigFile + } + #Start Server $App=Start-Process -FilePath $Launcher -WorkingDirectory $ServerPath -ArgumentList $ArgumentList -PassThru #Wait to see if the server is stable. diff --git a/main.ps1 b/main.ps1 index 5e480ef..e1eef42 100644 --- a/main.ps1 +++ b/main.ps1 @@ -4,7 +4,7 @@ [CmdletBinding()] param ( - [Parameter()] + [Parameter(Mandatory)] [string] $ServerCfg ) @@ -53,7 +53,7 @@ try { Get-ChildItem -Path ".\functions" -Include "*.psm1" -Recurse | Import-Module } catch { - Write-Warning "Unable to import functions." + Exit-WithError -ErrorMsg "Unable to import functions." } # Modules @@ -130,7 +130,7 @@ if ($MissingDependencies.Count -gt 0){ Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Verifying Server installation..." #--------------------------------------------------------- -[string]$FreshInstall=$false +[boolean]$FreshInstall=$false if (!(Test-Path $ServerExec)){ Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server is not installed : Installing $ServerName Server." Update-Server -ServerPath $ServerPath -SteamCMD $SteamCMD -SteamAppID $SteamAppID -Beta $Beta -BetaBuild $BetaBuild -BetaBuildPassword $BetaBuildPassword -UpdateType "Installing" @@ -144,7 +144,7 @@ Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Ver #--------------------------------------------------------- If ($UseWarnings -and !$FreshInstall) { - Send-RestartWarning -ProcessName $ProcessName -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -RestartTimers $RestartTimers -RestartMessageMinutes $RestartMessageMinutes -RestartMessageSeconds $RestartMessageSeconds -MessageCmd $MessageCmd -ServerStopCmd $ServerStopCmd -ServerSaveCmd $ServerSaveCmd + Send-RestartWarning -ProcessName $ProcessName -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -RestartTimers $RestartTimers -RestartMessageMinutes $RestartMessageMinutes -RestartMessageSeconds $RestartMessageSeconds -MessageCmd $MessageCmd -ServerStopCmd $ServerStopCmd -ServerSaveCmd $ServerSaveCmd -Protocol $Protocol } else { $Server=Get-Process $ProcessName -ErrorAction SilentlyContinue $Stopped=Stop-Server -Server $Server @@ -170,7 +170,7 @@ Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Upd #--------------------------------------------------------- if (!$FreshInstall) { - Update-Server -ServerPath $ServerPath -SteamCMD $SteamCMD -SteamAppID $SteamAppID -Beta $Beta -BetaBuild $BetaBuild -BetaBuildPassword $BetaBuildPassword -UpdateType "Updating" + #Update-Server -ServerPath $ServerPath -SteamCMD $SteamCMD -SteamAppID $SteamAppID -Beta $Beta -BetaBuild $BetaBuild -BetaBuildPassword $BetaBuildPassword -UpdateType "Updating" Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server successfully updated and/or verified." } diff --git a/modules/Get-Telnet.psm1 b/modules/Get-Telnet.psm1 new file mode 100644 index 0000000..7afda76 --- /dev/null +++ b/modules/Get-Telnet.psm1 @@ -0,0 +1,61 @@ +<# + Original Author : Martin Pugh + Twitter: @thesurlyadm1n + Spiceworks: Martin9700 + Blog: www.thesurlyadmin.com + Changelog: + 1.0 Initial Release + Link : http://community.spiceworks.com/scripts/show/1887-get-telnet-telnet-to-a-device-and-issue-commands +#> +Function Get-Telnet{ + [CmdletBinding()] + param ( + [Parameter()] + [OutputType([string])] + [string]$Command, + [string]$RemoteHost="127.0.0.1", + [string]$Port="23", + [string]$Password="", + [int32]$WaitTime=1000 + ) + [System.Collections.ArrayList]$Commands=@() + if ($Password -ne ""){ + $Commands.Add($Password) + $Commands.Add($Command) + } else { + $Commands.Add($Command) + } + #Attach to the remote device, setup streaming requirements + try { + $Socket = New-Object System.Net.Sockets.TcpClient($RemoteHost, $Port) + } + catch { + $Socket = $null + } + if ($Socket) + { $Stream = $Socket.GetStream() + $Writer = New-Object System.IO.StreamWriter($Stream) + $Buffer = New-Object System.Byte[] 1024 + #$Encoding = New-Object System.Text.AsciiEncoding + $Encoding = New-Object System.Text.UTF8Encoding + + #Now start issuing the commands + foreach ($Command in $Commands) + { $Writer.WriteLine($Command) + $Writer.Flush() + Start-Sleep -Milliseconds $WaitTime + } + #All commands issued, but since the last command is usually going to be + #the longest let's wait a little longer for it to finish + Start-Sleep -Milliseconds ($WaitTime * 4) + [string]$Result = "" + #Save all the results + while($Stream.DataAvailable) + { $Read = $Stream.Read($Buffer, 0, 1024) + $Result += ($Encoding.GetString($Buffer, 0, $Read)) + } + } else { + $Result = "Unable to connect to host: $($RemoteHost):$Port" + } + return $Result +} \ No newline at end of file diff --git a/modules/Send-RestartWarning.psm1 b/modules/Send-RestartWarning.psm1 index 8720ad1..57ae7a0 100644 --- a/modules/Send-RestartWarning.psm1 +++ b/modules/Send-RestartWarning.psm1 @@ -19,6 +19,27 @@ function Send-Command { } } +function Send-TelnetCommand { + [CmdletBinding()] + [OutputType([boolean])] + param ( + [Parameter(Mandatory)] + [string]$RconIP, + [int32]$RconPort, + [string]$RconPassword, + [string]$Command + ) + $Result=Get-Telnet -Command $Command -RemoteHost $RconIP -Port $RconPort -Password $RconPassword + Write-Host $Result + if (($Result -like "*Unable to connect to host:*") -or ($Result -like "*incorrect*")) { + Write-Warning "Unable to send command." + return $false + } else { + Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Command Sent." + return $true + } +} + function Send-RestartWarning { [CmdletBinding()] param ( @@ -34,7 +55,8 @@ function Send-RestartWarning { [string]$MessageCmd, [string]$ServerStopCmd, [Parameter(Mandatory=$false)] - [string]$ServerSaveCmd + [string]$ServerSaveCmd=$null, + [string]$protocol="RCON" ) $Server=Get-Process $ProcessName -ErrorAction SilentlyContinue $exited=$false @@ -57,8 +79,14 @@ function Send-RestartWarning { $TimerText=[string][Math]::Round($TimeLeft / 60,[MidpointRounding]::AwayFromZero) } $Message=$Message -replace "%", $TimerText - $Command="$MessageCmd $Message" - $Success=Send-Command -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $Command + if ($protocol -eq "RCON"){ + $Command="$MessageCmd $Message" + $Success=Send-Command -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $Command + } + if ($protocol -eq "Telnet"){ + $Command="$MessageCmd `"$Message`"" + $Success=Send-TelnetCommand -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $Command + } if ($Success) { Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Waiting $Timer seconds before next warning..." Start-Sleep -Seconds $Timer @@ -68,20 +96,30 @@ function Send-RestartWarning { } } if (!$exited){ - if (![string]::IsNullOrWhiteSpace($ServerSaveCmd)){ + if (-not ($ServerSaveCmd -eq $null)){ Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Saving server." - $Success=Send-Command -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerSaveCmd + if ($protocol -eq "RCON"){ + $Success=Send-Command -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerSaveCmd + } + if ($protocol -eq "Telnet"){ + $Success=Send-TelnetCommand -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerSaveCmd + } if ($Success) { - Start-Sleep -Seconds 10 + Start-Sleep -Seconds 5 } else { Write-Warning "Unable to send server save command." } } Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Closing server." - $Success=Send-Command -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerStopCmd + if ($protocol -eq "RCON"){ + $Success=Send-Command -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerStopCmd + } + if ($protocol -eq "Telnet"){ + $Success=Send-TelnetCommand -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerStopCmd + } if ($Success) { Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server closed." - Start-Sleep -Seconds 10 + Start-Sleep -Seconds 5 } else { Write-Warning "Unable to send server stop command." $Stopped=Stop-Server -Server $Server diff --git a/modules/Stop-Server.psm1 b/modules/Stop-Server.psm1 index 9dac310..99792c9 100644 --- a/modules/Stop-Server.psm1 +++ b/modules/Stop-Server.psm1 @@ -5,15 +5,15 @@ function Stop-Server { if(-not $Server.HasExited){ Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Closing Main Windows..." $Server.CloseMainWindow() - $Server.WaitForExit() - Start-Sleep -Seconds 10 + $Server.WaitForExit(30000) + Start-Sleep -Seconds 5 if ($Server.HasExited) { Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server succesfully shutdown." }else{ Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Trying again to stop the Server..." #Try Again Stop-Process $Server - Start-Sleep -Seconds 10 + Start-Sleep -Seconds 5 if ($Server.HasExited) { Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server succesfully shutdown on second try." }else{ @@ -23,7 +23,7 @@ function Stop-Server { } } } - Start-Sleep -Seconds 10 + Start-Sleep -Seconds 5 if ($Server.HasExited) { return $true } else { From 02a65acb3452ccec30dfac853963936431d1f21c Mon Sep 17 00:00:00 2001 From: Patrick Veilleux Date: Thu, 26 Aug 2021 21:03:03 -0400 Subject: [PATCH 4/8] correct formating --- configs/7daystodie.psm1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/7daystodie.psm1 b/configs/7daystodie.psm1 index 35219ab..8c73733 100644 --- a/configs/7daystodie.psm1 +++ b/configs/7daystodie.psm1 @@ -5,6 +5,7 @@ #--------------------------------------------------------- # Server Configuration #--------------------------------------------------------- + #Server Configuration [string]$ConfigFile="$Env:userprofile\AppData\Roaming\7DaysToDie\Saves\serverconfig.xml" @@ -93,6 +94,7 @@ Core 8=> 10000000=> 128 #--------------------------------------------------------- # Restart Warnings (Require RCON) #--------------------------------------------------------- + #Use Rcon to restart server softly. [bool]$UseWarnings=$true From 5303e01a975fd776230db0a68ffcbdc496b37f9d Mon Sep 17 00:00:00 2001 From: Patrick Veilleux Date: Sat, 28 Aug 2021 18:12:31 -0400 Subject: [PATCH 5/8] Add 7 Days to die Support. --- configs/7daystodie.psm1 | 200 ++++++++++++++++++++++------------------ 1 file changed, 110 insertions(+), 90 deletions(-) diff --git a/configs/7daystodie.psm1 b/configs/7daystodie.psm1 index 8c73733..89d54a5 100644 --- a/configs/7daystodie.psm1 +++ b/configs/7daystodie.psm1 @@ -2,132 +2,149 @@ #Change your servers settings in C:\Users\%username%\AppData\Roaming\7DaysToDie\Saves\serverconfig.xml #> +$Name = "7DaysToDie" + #--------------------------------------------------------- # Server Configuration #--------------------------------------------------------- -#Server Configuration -[string]$ConfigFile="$Env:userprofile\AppData\Roaming\7DaysToDie\Saves\serverconfig.xml" +$ServerDetails = @{ + #Server Configuration + ConfigFile = "$Env:userprofile\AppData\Roaming\7DaysToDie\Saves\serverconfig.xml" -#Rcon IP, usually localhost -[string]$RconIP="127.0.0.1" + #Rcon IP, usually localhost + ManagementIP = "127.0.0.1" -#Rcon Port in serverconfig.xml -[int32]$RconPort=8081 + #Rcon Port in serverconfig.xml + ManagementPort = 8081 -#Rcon Password as set in serverconfig.xml -[string]$RconPassword="" + #Rcon Password as set in serverconfig.xml nothing is localhost only. + ManagementPassword = "" -#Server Log File -[string]$ServerLogFile="$Env:userprofile\AppData\Roaming\7DaysToDie\Logs\$(Get-TimeStamp).txt" + #Server Log File + LogFile = "$Env:userprofile\AppData\Roaming\7DaysToDie\Logs\$(Get-TimeStamp).txt" #--------------------------------------------------------- -# Server Installation +# Server Installation Details #--------------------------------------------------------- -#Name of the Server Instance -[string]$ServerName="7DaysToDie" + #Name of the Server Instance + Name = $Name -#Server Installation Path -[string]$ServerPath=".\servers\$ServerName" + #Server Installation Path + Path = ".\servers\$Name" -#Steam Server App Id -[int32]$SteamAppID=294420 + #Steam Server App Id + AppID = 294420 -#Use Beta builds $true or $false -[bool]$Beta=$false + #Use Beta builds $true or $false + Beta = $false -#Name of the Beta Build -[string]$BetaBuild="iwillbackupmysave" + #Name of the Beta Build + BetaBuild = "iwillbackupmysave" -#Beta Build Password -[string]$BetaBuildPassword="iaccepttheconsequences" + #Beta Build Password + BetaBuildPassword = "iaccepttheconsequences" -#Process name in the task manager -[string]$ProcessName="7DaysToDieServer" + #Process name in the task manager + ProcessName = "7DaysToDieServer" -#ProjectZomboid64.exe -[string]$ServerExec=".\servers\$ServerName\7DaysToDieServer.exe" + #ProjectZomboid64.exe + Exec = ".\servers\$Name\7DaysToDieServer.exe" -#Process Priority Realtime, High, Above normal, Normal, Below normal, Low -[bool]$UsePriority=$true -[string]$AppPriority="High" + #Process Priority Realtime, High, Above normal, Normal, Below normal, Low + UsePriority = $true + AppPriority = "High" -<# -Process Affinity (Core Assignation) -Core 1=> 00000001=> 1 -Core 2=> 00000010=> 2 -Core 3=> 00000100=> 4 -Core 4=> 00001000=> 8 -Core 5=> 00010000=> 16 -Core 6=> 00100000=> 32 -Core 7=> 01000000=> 64 -Core 8=> 10000000=> 128 -========================== -8 Cores=> 11111111=> 255 -4 Cores=> 00001111=> 15 -2 Cores=> 00000011=> 3 -#> + <# + Process Affinity (Core Assignation) + Core 1 = > 00000001 = > 1 + Core 2 = > 00000010 = > 2 + Core 3 = > 00000100 = > 4 + Core 4 = > 00001000 = > 8 + Core 5 = > 00010000 = > 16 + Core 6 = > 00100000 = > 32 + Core 7 = > 01000000 = > 64 + Core 8 = > 10000000 = > 128 + = = = = = = = = = = = = = = = = = = = = = = = = = = + 8 Cores = > 11111111 = > 255 + 4 Cores = > 00001111 = > 15 + 2 Cores = > 00000011 = > 3 + #> -[bool]$UseAffinity=$false -[int32]$AppAffinity=15 + UseAffinity = $false + AppAffinity = 15 +} +#Create the object +$Server = New-Object -TypeName PsObject -Property $ServerDetails #--------------------------------------------------------- # Backups #--------------------------------------------------------- -#Do Backups -[bool]$UseBackups=$true +$BackupsDetails = @{ + #Do Backups + Use = $true -#Backup Folder -[string]$BackupPath=".\backups\$ServerName" + #Backup Folder + Path = ".\backups\$($Server.Name)" -#Number of days of backups to keep. -[int32]$BackupDays=7 + #Number of days of backups to keep. + Days = 7 -#Number of weeks of weekly backups to keep. -[int32]$BackupWeeks=4 + #Number of weeks of weekly backups to keep. + Weeks = 4 -#Folder to include in backup -[string]$ServerSaves="$Env:userprofile\AppData\Roaming\7DaysToDie" + #Folder to include in backup + Saves = "$Env:userprofile\AppData\Roaming\7DaysToDie" +} +#Create the object +$Backups = New-Object -TypeName PsObject -Property $BackupsDetails #--------------------------------------------------------- -# Restart Warnings (Require RCON) +# Restart Warnings (Require RCON, Telnet or WebSocket API) #--------------------------------------------------------- -#Use Rcon to restart server softly. -[bool]$UseWarnings=$true +$WarningsDetails = @{ + #Use Rcon to restart server softly. + Use = $true -#Use Telnet protocol instead of RCON -[string]$protocol="Telnet" + #What protocol to use : Rcon, Telnet, Websocket + Protocol = "Telnet" -#Times at which the servers will warn the players that it is about to restart. (in seconds between each timers) -[System.Collections.ArrayList]$RestartTimers=@(240,50,10) #Total wait time is 240+50+10=300 seconds or 5 minutes + #Times at which the servers will warn the players that it is about to restart. (in seconds between each timers) + Timers = [System.Collections.ArrayList]@(240,50,10) #Total wait time is 240+50+10 = 300 seconds or 5 minutes -#message that will be sent. % is a wildcard for the timer. -[string]$RestartMessageMinutes="The server will restart in % minutes !" + #message that will be sent. % is a wildcard for the timer. + MessageMin = "The server will restart in % minutes !" -#message that will be sent. % is a wildcard for the timer. -[string]$RestartMessageSeconds="The server will restart in % seconds !" + #message that will be sent. % is a wildcard for the timer. + MessageSec = "The server will restart in % seconds !" -#command to send a message. -[string]$MessageCmd="say" + #command to send a message. + CmdMessage = "say" -#command to save the server -[string]$ServerSaveCmd="saveworld" + #command to save the server + CmdSave = "saveworld" -#command to stop the server -[string]$ServerStopCmd="shutdown" + #How long to wait in seconds after the save command is sent. + SaveDelay = 15 + + #command to stop the server + CmdStop = "shutdown" +} +#Create the object +$Warnings = New-Object -TypeName PsObject -Property $WarningsDetails #--------------------------------------------------------- # Launch Arguments #--------------------------------------------------------- #Launch Arguments -[string]$ArgumentList="-logfile $ServerLogFile -configfile=$ConfigFile -batchmode -nographics -dedicated -quit" +$ArgumentList = "-logfile $($Server.LogFile) -configfile=$($Server.ConfigFile) -batchmode -nographics -dedicated -quit" #Server Launcher -[string]$Launcher=$ServerExec +$Launcher = $Server.Exec #--------------------------------------------------------- # Launch Function @@ -135,27 +152,30 @@ Core 8=> 10000000=> 128 function Start-Server { #Copy Config File if not created. Do not modify the one in the server directory, it will be overwriten on updates. - If(-Not (Test-Path -Path $ConfigFile -PathType "leaf")){ - Copy-Item -Path "$ServerPath\serverconfig.xml" -Destination $ConfigFile + $ConfigFilePath = Split-Path -Path $Server.ConfigFile + if (-not(Test-Path -Path $ConfigFilePath)){ + New-Item -ItemType "directory" -Path $ConfigFilePath -Force -ErrorAction SilentlyContinue + } + If(-not (Test-Path -Path $Server.ConfigFile -PathType "leaf")){ + Copy-Item -Path "$($Server.Path)\serverconfig.xml" -Destination $Server.ConfigFile -Force } #Start Server - $App=Start-Process -FilePath $Launcher -WorkingDirectory $ServerPath -ArgumentList $ArgumentList -PassThru + $App = Start-Process -FilePath $Launcher -WorkingDirectory $Server.Path -ArgumentList $ArgumentList -PassThru #Wait to see if the server is stable. Start-Sleep -Seconds 10 - if ($App.HasExited){ + if (-not ($App) -or $App.HasExited){ Write-Warning "Server Failed to launch." } else { - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server Started." - } - - # Set the priority and affinity - if ($UsePriority) { - $App.PriorityClass=$AppPriority - } - if ($UseAffinity){ - $App.ProcessorAffinity=$AppAffinity + Write-ServerMsg "Server Started." + # Set the priority and affinity + if ($Server.UsePriority) { + $App.PriorityClass = $Server.AppPriority + } + if ($Server.UseAffinity){ + $App.ProcessorAffinity = $Server.AppAffinity + } } } -Export-ModuleMember -Function * -Variable * \ No newline at end of file +Export-ModuleMember -Function Start-Server -Variable @("Server","Backups","Warnings") \ No newline at end of file From 5aae45851176c2704f51645aaa3abf7ec0e7fda0 Mon Sep 17 00:00:00 2001 From: Patrick Veilleux Date: Sat, 28 Aug 2021 18:24:37 -0400 Subject: [PATCH 6/8] refactor into globals objects. --- .vscode/PSScriptAnalyzerSettings.psd1 | 4 +- configs/global.psm1 | 35 +++- configs/projectzomboid.psm1 | 186 +++++++++++-------- functions/Backup-Server.psm1 | 34 ++++ functions/Core-Functions.psm1 | 29 --- functions/Exit-WithError.psm1 | 14 ++ {modules => functions}/Get-Telnet.psm1 | 17 +- functions/Get-TimeStamp.psm1 | 5 + {modules => functions}/Install-Mcrcon.psm1 | 10 +- {modules => functions}/Install-SevenZip.psm1 | 10 +- {modules => functions}/Install-SteamCMD.psm1 | 3 +- functions/Remove-OldLog.psm1 | 6 + functions/Send-Command.psm1 | 45 +++++ functions/Send-RestartWarning.psm1 | 49 +++++ functions/Stop-Server.psm1 | 33 ++++ functions/Update-Server.psm1 | 29 +++ functions/Write-ScriptMsg.psm1 | 10 + functions/Write-ServerMsg.psm1 | 10 + main.ps1 | 162 +++++++--------- modules/Backup-Server.psm1 | 45 ----- modules/Send-RestartWarning.psm1 | 136 -------------- modules/Stop-Server.psm1 | 33 ---- modules/Update-Server.psm1 | 36 ---- run.cmd | 2 +- 24 files changed, 457 insertions(+), 486 deletions(-) create mode 100644 functions/Backup-Server.psm1 delete mode 100644 functions/Core-Functions.psm1 create mode 100644 functions/Exit-WithError.psm1 rename {modules => functions}/Get-Telnet.psm1 (81%) create mode 100644 functions/Get-TimeStamp.psm1 rename {modules => functions}/Install-Mcrcon.psm1 (58%) rename {modules => functions}/Install-SevenZip.psm1 (57%) rename {modules => functions}/Install-SteamCMD.psm1 (81%) create mode 100644 functions/Remove-OldLog.psm1 create mode 100644 functions/Send-Command.psm1 create mode 100644 functions/Send-RestartWarning.psm1 create mode 100644 functions/Stop-Server.psm1 create mode 100644 functions/Update-Server.psm1 create mode 100644 functions/Write-ScriptMsg.psm1 create mode 100644 functions/Write-ServerMsg.psm1 delete mode 100644 modules/Backup-Server.psm1 delete mode 100644 modules/Send-RestartWarning.psm1 delete mode 100644 modules/Stop-Server.psm1 delete mode 100644 modules/Update-Server.psm1 diff --git a/.vscode/PSScriptAnalyzerSettings.psd1 b/.vscode/PSScriptAnalyzerSettings.psd1 index 5a87065..a11615c 100644 --- a/.vscode/PSScriptAnalyzerSettings.psd1 +++ b/.vscode/PSScriptAnalyzerSettings.psd1 @@ -1,6 +1,6 @@ @{ - Severity=@('Error','Warning') - ExcludeRules=@( + Severity = @('Error','Warning') + ExcludeRules = @( 'PSUseDeclaredVarsMoreThanAssignments', 'PSUseShouldProcessForStateChangingFunctions', 'PSProvideCommentHelp', diff --git a/configs/global.psm1 b/configs/global.psm1 index 9f0dedc..627f8dd 100644 --- a/configs/global.psm1 +++ b/configs/global.psm1 @@ -1,13 +1,30 @@ -#7zip -[string]$SevenZip=".\tools\7z\7za.exe" +$GlobalDetails = @{ + #7zip + SevenZip = ".\tools\7z\7za.exe" -#mcrcon -[string]$Mcrcon=".\tools\mcrcon\mcrcon.exe" + #mcrcon + Mcrcon = ".\tools\mcrcon\mcrcon.exe" -#SteamCMD -[string]$SteamCMD=".\tools\SteamCMD\steamcmd.exe" + #SteamCMD + SteamCMD = ".\tools\SteamCMD\steamcmd.exe" -#Path of the logs folder. -[string]$LogFolder=".\logs" + #Path of the logs folder. + LogFolder = ".\logs" -Export-ModuleMember -Variable * + #Number of days to keep server logs + Days = 30 + + #Console Output Text Color + FgColor = "Green" + + #Console Output Text Color for sections + SectionColor = "Blue" + + #Console Output Background Color + BgColor = "Black" +} + +#Create the object +$Global = New-Object -TypeName PsObject -Property $GlobalDetails + +Export-ModuleMember -Variable "Global" diff --git a/configs/projectzomboid.psm1 b/configs/projectzomboid.psm1 index 98a78f5..c1668f4 100644 --- a/configs/projectzomboid.psm1 +++ b/configs/projectzomboid.psm1 @@ -28,146 +28,168 @@ SteamPort1=8766 SteamPort2=8767 ``` You do not need to forward RCON. - #> +$Name = "ProjectZomboid" + #--------------------------------------------------------- # Server Configuration #--------------------------------------------------------- -#Rcon IP, usually localhost -[string]$RconIP="127.0.0.1" -#Rcon Port in servertest.ini -[int32]$RconPort=27015 +$ServerDetails = @{ + + #Rcon IP, usually localhost + ManagementIP = "127.0.0.1" + + #Rcon Port in servertest.ini + ManagementPort = 27015 -#Rcon Password as set in servertest.ini (Do not use " " in servertest.ini) -[string]$RconPassword="CHANGEME" + #Rcon Password as set in servertest.ini (Do not use " " in servertest.ini) + ManagementPassword = "CHANGEME" #--------------------------------------------------------- # Server Installation #--------------------------------------------------------- -#Name of the Server Instance -[string]$ServerName="ProjectZomboid" + #Name of the Server Instance + Name = $Name -#Server Installation Path -[string]$ServerPath=".\servers\$ServerName" + #Server Installation Path + Path = ".\servers\$Name" -#Steam Server App Id -[int32]$SteamAppID=380870 + #Steam Server App Id + AppID = 380870 -#Use Beta builds $true or $false -[bool]$Beta=$false + #Use Beta builds $true or $false + Beta = $false -#Name of the Beta Build -[string]$BetaBuild="iwillbackupmysave" + #Name of the Beta Build + BetaBuild = "iwillbackupmysave" -#Beta Build Password -[string]$BetaBuildPassword="iaccepttheconsequences" + #Beta Build Password + BetaBuildPassword = "iaccepttheconsequences" -#Process name in the task manager -[string]$ProcessName="java" + #Process name in the task manager + ProcessName = "java" -#ProjectZomboid64.exe -[string]$ServerExec=".\servers\$ServerName\ProjectZomboid64.exe" + #ProjectZomboid64.exe + Exec = ".\servers\$Name\ProjectZomboid64.exe" -#Process Priority Realtime, High, Above normal, Normal, Below normal, Low -[bool]$UsePriority=$true -[string]$AppPriority="High" + #Process Priority Realtime, High, Above normal, Normal, Below normal, Low + UsePriority = $true + AppPriority = "High" -<# -Process Affinity (Core Assignation) -Core 1=> 00000001=> 1 -Core 2=> 00000010=> 2 -Core 3=> 00000100=> 4 -Core 4=> 00001000=> 8 -Core 5=> 00010000=> 16 -Core 6=> 00100000=> 32 -Core 7=> 01000000=> 64 -Core 8=> 10000000=> 128 -========================== -8 Cores=> 11111111=> 255 -4 Cores=> 00001111=> 15 -2 Cores=> 00000011=> 3 -#> + <# + Process Affinity (Core Assignation) + Core 1 = > 00000001 = > 1 + Core 2 = > 00000010 = > 2 + Core 3 = > 00000100 = > 4 + Core 4 = > 00001000 = > 8 + Core 5 = > 00010000 = > 16 + Core 6 = > 00100000 = > 32 + Core 7 = > 01000000 = > 64 + Core 8 = > 10000000 = > 128 + = = = = = = = = = = = = = = = = = = = = = = = = = = + 8 Cores = > 11111111 = > 255 + 4 Cores = > 00001111 = > 15 + 2 Cores = > 00000011 = > 3 + #> -[bool]$UseAffinity=$false -[int32]$AppAffinity=15 + UseAffinity = $false + AppAffinity = 15 +} +#Create the object +$Server = New-Object -TypeName PsObject -Property $ServerDetails #--------------------------------------------------------- # Backups #--------------------------------------------------------- +$BackupsDetails = @{ + #Do Backups + Use = $true -#Do Backups -[bool]$UseBackups=$true - -#Backup Folder -[string]$BackupPath=".\backups\$ServerName" + #Backup Folder + Path = ".\backups\$($Server.Name)" -#Number of days of backups to keep. -[int32]$BackupDays=7 + #Number of days of backups to keep. + Days = 7 -#Number of weeks of weekly backups to keep. -[int32]$BackupWeeks=4 + #Number of weeks of weekly backups to keep. + Weeks = 4 -#Folder to include in backup -[string]$ServerSaves="$Env:userprofile\Zomboid" + #Folder to include in backup + Saves = "$Env:userprofile\Zomboid" +} +#Create the object +$Backups = New-Object -TypeName PsObject -Property $BackupsDetails #--------------------------------------------------------- -# Restart Warnings (Require RCON) +# Restart Warnings (Require RCON, Telnet or WebSocket API) #--------------------------------------------------------- -#Use Rcon to restart server softly. -[bool]$UseWarnings=$true +$WarningsDetails = @{ + #Use Rcon to restart server softly. + Use = $true + + #What protocol to use : Rcon, Telnet, Websocket + Protocol = "Telnet" + + #Times at which the servers will warn the players that it is about to restart. (in seconds between each timers) + Timers = [System.Collections.ArrayList]@(240,50,10) #Total wait time is 240+50+10 = 300 seconds or 5 minutes + + #message that will be sent. % is a wildcard for the timer. + MessageMin = "The server will restart in % minutes !" -#Times at which the servers will warn the players that it is about to restart. (in seconds between each timers) -[System.Collections.ArrayList]$RestartTimers=@(240,50,10) #Total wait time is 240+50+10=300 seconds or 5 minutes + #message that will be sent. % is a wildcard for the timer. + MessageSec = "The server will restart in % seconds !" -#message that will be sent. % is a wildcard for the timer. -[string]$RestartMessageMinutes="The server will restart in % minutes !" + #command to send a message. + CmdMessage = "servermsg" -#message that will be sent. % is a wildcard for the timer. -[string]$RestartMessageSeconds="The server will restart in % seconds !" + #command to save the server + CmdSave = "save" -#command to send a message. -[string]$MessageCmd="servermsg" + #How long to wait in seconds after the save command is sent. + SaveDelay = 15 -#command to stop the server -[string]$ServerStopCmd="quit" + #command to stop the server + CmdStop = "quit" +} +#Create the object +$Warnings = New-Object -TypeName PsObject -Property $WarningsDetails #--------------------------------------------------------- # Launch Arguments #--------------------------------------------------------- #Java Arguments -[string]$PZ_CLASSPATH="java/jinput.jar;java/lwjgl.jar;java/lwjgl_util.jar;java/sqlite-jdbc-3.8.10.1.jar;java/trove-3.0.3.jar;java/uncommons-maths-1.2.3.jar;java/javacord-2.0.17-shaded.jar;java/guava-23.0.jar;java/" +$PZ_CLASSPATH = "java/jinput.jar;java/lwjgl.jar;java/lwjgl_util.jar;java/sqlite-jdbc-3.8.10.1.jar;java/trove-3.0.3.jar;java/uncommons-maths-1.2.3.jar;java/javacord-2.0.17-shaded.jar;java/guava-23.0.jar;java/" #Launch Arguments -[string]$ArgumentList="-Dzomboid.steam=1 -Dzomboid.znetlog=1 -XX:+UseConcMarkSweepGC -XX:-CreateMinidumpOnCrash -XX:-OmitStackTraceInFastThrow -Xms2048m -Xmx2048m -Djava.library.path=natives/;. -cp $PZ_CLASSPATH zombie.network.GameServer" +$ArgumentList = "-Dzomboid.steam = 1 -Dzomboid.znetlog = 1 -XX:+UseConcMarkSweepGC -XX:-CreateMinidumpOnCrash -XX:-OmitStackTraceInFastThrow -Xms2048m -Xmx2048m -Djava.library.path = natives/;. -cp $PZ_CLASSPATH zombie.network.GameServer" -[string]$Launcher="$ServerPath\jre64\bin\java.exe" +$Launcher = "$($Server.Path)\jre64\bin\java.exe" #--------------------------------------------------------- # Launch Function #--------------------------------------------------------- function Start-Server { - $App=Start-Process -FilePath $Launcher -WorkingDirectory $ServerPath -ArgumentList $ArgumentList -PassThru + $App = Start-Process -FilePath $Launcher -WorkingDirectory $Server.Path -ArgumentList $ArgumentList -PassThru #Wait to see if the server is stable. Start-Sleep -Seconds 10 - if ($App.HasExited){ + if (-not ($App) -or $App.HasExited){ Write-Warning "Server Failed to launch." } else { - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server Started." - } - - # Set the priority and affinity - if ($UsePriority) { - $App.PriorityClass=$AppPriority - } - if ($UseAffinity){ - $App.ProcessorAffinity=$AppAffinity + Write-ServerMsg "Server Started." + # Set the priority and affinity + if ($Server.UsePriority) { + $App.PriorityClass = $Server.AppPriority + } + if ($Server.UseAffinity){ + $App.ProcessorAffinity = $Server.AppAffinity + } } } -Export-ModuleMember -Function * -Variable * \ No newline at end of file +Export-ModuleMember -Function Start-Server -Variable @("Server","Backups","Warnings") \ No newline at end of file diff --git a/functions/Backup-Server.psm1 b/functions/Backup-Server.psm1 new file mode 100644 index 0000000..bb5bcf7 --- /dev/null +++ b/functions/Backup-Server.psm1 @@ -0,0 +1,34 @@ +function Backup-Server { + Write-ServerMsg "Creating Backup." + #Create backup name from date and time + $BackupName = Get-TimeStamp + #Check if it's friday (Sunday is 0) + if ((Get-Date -UFormat %u) -eq 5){ + $Type = "Weekly" + $Limit = (Get-Date).AddDays(-($Backups.Weeks * 7)) + } else { + $Type = "Daily" + $Limit = (Get-Date).AddDays(-$Backups.Days) + } + #Check if directory exist and create it. + if (-not(Test-Path -Path "$($Backups.Path)\$Type" -PathType "Container")){ + New-Item -Path "$($Backups.Path)\$Type" -ItemType "directory" -ErrorAction SilentlyContinue + } + #Wait for server to have unlocked files + Start-Sleep -Seconds 5 + #Run Backup + try { + & $Global.SevenZip a -tzip -mx=1 "$($Backups.Path)\$Type\$BackupName.zip" $Backups.Saves + } + catch { + Exit-WithError -ErrorMsg "Unable to backup server." + } + + Write-ServerMsg "Backup Created : $BackupName.zip" + + #Delete old backups + Write-ServerMsg "Deleting old backups." + Get-ChildItem -Path "$($Backups.Path)\$Type" -Recurse -Force | Where-Object { -not ($_.PSIsContainer) -and $_.LastWriteTime -lt $Limit } | Remove-Item -Force +} + +Export-ModuleMember -Function Backup-Server \ No newline at end of file diff --git a/functions/Core-Functions.psm1 b/functions/Core-Functions.psm1 deleted file mode 100644 index 1e108ec..0000000 --- a/functions/Core-Functions.psm1 +++ /dev/null @@ -1,29 +0,0 @@ -Function Get-TimeStamp { - return Get-Date -Format "yyyy-MM-dd_HH-mm-ss" -} - -function Exit-WithError -{ - param - ( - [string]$ErrorMsg - ) - Write-Host -ForegroundColor "Red" -BackgroundColor "Black" -Object $ErrorMsg - Stop-Transcript - Read-Host - exit -} - -function Remove-OldLog { - [CmdletBinding()] - param ( - [string]$LogFolder, - [int32]$Days=30 - ) - #Delete old logs - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Deleting logs older than $Days days." - $Limit=(Get-Date).AddDays(-$Days) - Get-ChildItem -Path $LogFolder -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.LastWriteTime -lt $Limit } | Remove-Item -Force -} - -Export-ModuleMember -Function Get-TimeStamp, Exit-WithError, Remove-OldLog \ No newline at end of file diff --git a/functions/Exit-WithError.psm1 b/functions/Exit-WithError.psm1 new file mode 100644 index 0000000..d3636fa --- /dev/null +++ b/functions/Exit-WithError.psm1 @@ -0,0 +1,14 @@ +function Exit-WithError +{ + [CmdletBinding()] + param ( + [Parameter(Mandatory)] + [string]$ErrorMsg + ) + Write-Host -ForegroundColor "Red" -BackgroundColor "Black" -Object $ErrorMsg + Stop-Transcript + Read-Host + exit +} + +Export-ModuleMember -Function Exit-WithError \ No newline at end of file diff --git a/modules/Get-Telnet.psm1 b/functions/Get-Telnet.psm1 similarity index 81% rename from modules/Get-Telnet.psm1 rename to functions/Get-Telnet.psm1 index 7afda76..1d1e555 100644 --- a/modules/Get-Telnet.psm1 +++ b/functions/Get-Telnet.psm1 @@ -9,16 +9,15 @@ #> Function Get-Telnet{ [CmdletBinding()] + [OutputType([string])] param ( [Parameter()] - [OutputType([string])] [string]$Command, - [string]$RemoteHost="127.0.0.1", - [string]$Port="23", - [string]$Password="", - [int32]$WaitTime=1000 + [string]$RemoteHost = "127.0.0.1", + [string]$Port = "23", + [string]$Password = "" ) - [System.Collections.ArrayList]$Commands=@() + [System.Collections.ArrayList]$Commands = @() if ($Password -ne ""){ $Commands.Add($Password) $Commands.Add($Command) @@ -43,16 +42,16 @@ Function Get-Telnet{ foreach ($Command in $Commands) { $Writer.WriteLine($Command) $Writer.Flush() - Start-Sleep -Milliseconds $WaitTime + Start-Sleep -Seconds 1 } #All commands issued, but since the last command is usually going to be #the longest let's wait a little longer for it to finish - Start-Sleep -Milliseconds ($WaitTime * 4) + Start-Sleep -Seconds 5 [string]$Result = "" #Save all the results while($Stream.DataAvailable) { $Read = $Stream.Read($Buffer, 0, 1024) - $Result += ($Encoding.GetString($Buffer, 0, $Read)) + $Result += ($Encoding.GetString($Buffer, 0, $Read)) } } else { $Result = "Unable to connect to host: $($RemoteHost):$Port" diff --git a/functions/Get-TimeStamp.psm1 b/functions/Get-TimeStamp.psm1 new file mode 100644 index 0000000..c2621ff --- /dev/null +++ b/functions/Get-TimeStamp.psm1 @@ -0,0 +1,5 @@ +Function Get-TimeStamp { + return Get-Date -Format "yyyy-MM-dd_HH-mm-ss" +} + +Export-ModuleMember -Function Get-TimeStamp \ No newline at end of file diff --git a/modules/Install-Mcrcon.psm1 b/functions/Install-Mcrcon.psm1 similarity index 58% rename from modules/Install-Mcrcon.psm1 rename to functions/Install-Mcrcon.psm1 index d2c2f47..3190cdf 100644 --- a/modules/Install-Mcrcon.psm1 +++ b/functions/Install-Mcrcon.psm1 @@ -1,15 +1,15 @@ -function Install-mcrcon { +function Install-Mcrcon { [CmdletBinding()] param ( [Parameter(Mandatory)] [string]$Application ) - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Downloading mcrcon." + Write-ServerMsg "Downloading mcrcon." New-Item -Path (Split-Path -Path $Application) -ItemType "directory" Invoke-WebRequest -Uri "https://github.com/Tiiffi/mcrcon/releases/download/v0.7.1/mcrcon-0.7.1-windows-x86-32.zip" -OutFile ".\downloads\mcrcon.zip" -ErrorAction SilentlyContinue Expand-Archive -Path ".\downloads\mcrcon.zip" -DestinationPath ".\downloads\mcrcon\" -Force - $McrconPath=Resolve-Path -Path ".\downloads\mcrcon\mcrcon-0.7.1-windows-x86-32\mcrcon.exe" - Copy-Item -Path $McrconPath -Destination $Application -Force + Copy-Item -Path ".\downloads\mcrcon\mcrcon-0.7.1-windows-x86-32\mcrcon.exe" -Destination $Application -Force + Write-ServerMsg "Mcrcon Installed." } -Export-ModuleMember -Function Install-mcrcon \ No newline at end of file +Export-ModuleMember -Function Install-Mcrcon \ No newline at end of file diff --git a/modules/Install-SevenZip.psm1 b/functions/Install-SevenZip.psm1 similarity index 57% rename from modules/Install-SevenZip.psm1 rename to functions/Install-SevenZip.psm1 index 9834675..cfc1a0c 100644 --- a/modules/Install-SevenZip.psm1 +++ b/functions/Install-SevenZip.psm1 @@ -4,15 +4,15 @@ function Install-SevenZip { [Parameter(Mandatory)] [string]$Application ) - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Installing 7Zip Portable." - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Downloading 7zip 9.20 to extract 7zip 19.00" + Write-ServerMsg "Installing 7Zip Portable." + Write-ServerMsg "Downloading 7zip 9.20 to extract 7zip 19.00" Invoke-WebRequest -Uri "https://www.7-zip.org/a/7za920.zip" -OutFile ".\downloads\7za920.zip" Expand-Archive -Path ".\downloads\7za920.zip" -DestinationPath ".\downloads\7z920\" -Force - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Downloading 7zip 19.00" + Write-ServerMsg "Downloading 7zip 19.00" Invoke-WebRequest -Uri "https://www.7-zip.org/a/7z1900-extra.7z" -OutFile ".\downloads\7z1900-extra.7z" -ErrorAction SilentlyContinue - $7z920=Resolve-Path -Path ".\downloads\7z920\7za.exe" - & $7z920 x ".\downloads\7z1900-extra.7z" -o".\downloads\7z1900\" -y + & ".\downloads\7z920\7za.exe" x ".\downloads\7z1900-extra.7z" -o".\downloads\7z1900\" -y Copy-Item -Path ".\downloads\7z1900\x64\" -Destination (Split-Path -Path $Application) -Recurse -Force + Write-ServerMsg "7Zip Installed." } Export-ModuleMember -Function Install-SevenZip diff --git a/modules/Install-SteamCMD.psm1 b/functions/Install-SteamCMD.psm1 similarity index 81% rename from modules/Install-SteamCMD.psm1 rename to functions/Install-SteamCMD.psm1 index efc5430..9f4b099 100644 --- a/modules/Install-SteamCMD.psm1 +++ b/functions/Install-SteamCMD.psm1 @@ -4,9 +4,10 @@ function Install-SteamCMD { [Parameter(Mandatory)] [string]$Application ) - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Downloading SteamCMD." + Write-ServerMsg "Downloading SteamCMD." Invoke-WebRequest -Uri "https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip" -OutFile ".\downloads\steamcmd.zip" -ErrorAction SilentlyContinue Expand-Archive -Path ".\downloads\steamcmd.zip" -DestinationPath (Split-Path -Path $Application) -Force + Write-ServerMsg "SteamCMD Installed." } Export-ModuleMember -Function Install-SteamCMD \ No newline at end of file diff --git a/functions/Remove-OldLog.psm1 b/functions/Remove-OldLog.psm1 new file mode 100644 index 0000000..cd1cd15 --- /dev/null +++ b/functions/Remove-OldLog.psm1 @@ -0,0 +1,6 @@ +function Remove-OldLog { + $Limit = (Get-Date).AddDays(-$Global.Days) + Get-ChildItem -Path $Global.LogFolder -Recurse | Where-Object { -not ($_.PSIsContainer) -and $_.LastWriteTime -lt $Limit } | Remove-Item -Force -ErrorAction SilentlyContinue +} + +Export-ModuleMember -Function Remove-OldLog \ No newline at end of file diff --git a/functions/Send-Command.psm1 b/functions/Send-Command.psm1 new file mode 100644 index 0000000..5bd17c7 --- /dev/null +++ b/functions/Send-Command.psm1 @@ -0,0 +1,45 @@ +function Send-Command { + [CmdletBinding()] + [OutputType([boolean])] + param ( + [Parameter()] + $Command, + $Message = "" + ) + + $Result = $null + $Success = $false + #Select Protocol + switch ($Warnings.Protocol) { + "Rcon" { + $Result = Start-Process $Global.Mcrcon -ArgumentList "-c -H $($Server.ManagementIP) -P $($Server.ManagementPort) -p $($Server.ManagementPassword) `"$Command $Message`"" -Wait -PassThru -NoNewWindow + if ($Result.ExitCode -eq 0) { + $Success = $true + } + } + + "Telnet" { + $Result = Get-Telnet -Command "$Command `"$Message`"" -RemoteHost $Server.ManagementIP -Port $Server.ManagementPort -Password $Server.ManagementPassword + Write-Host $Result + if (-not(($Result -like "*Unable to connect to host:*") -or ($Result -like "*incorrect*"))) { + $Success = $true + } + } + + "Websocket" { + Write-Warning "Protocol Not Implemented Yet" + } + + Default { + Write-Warning "Protocol $($Warnings.Protocol) Not Found" + } + } + if ($Success) { + Write-ServerMsg "Command Sent." + } else { + Write-ServerMsg "Failed to send command." + } + Return $Success +} + +Export-ModuleMember -Function Send-Command \ No newline at end of file diff --git a/functions/Send-RestartWarning.psm1 b/functions/Send-RestartWarning.psm1 new file mode 100644 index 0000000..c183340 --- /dev/null +++ b/functions/Send-RestartWarning.psm1 @@ -0,0 +1,49 @@ +function Send-RestartWarning { + [CmdletBinding()] + [OutputType([boolean])] + param ( + [Parameter(Mandatory)] + $ServerProcess + ) + $Stopped = $false + while ($Warnings.Timers.Count -gt 0) { + $Timer = $Warnings.Timers[0] + $TimeLeft = 0 + $Warnings.Timers | ForEach-Object { $TimeLeft += $_} + $Warnings.Timers.RemoveAt(0) + if ($TimeLeft -lt 60) { + $Message = $Warnings.MessageSec + $TimerText = [string]$TimeLeft + } else { + $Message = $Warnings.MessageMin + $TimerText = [string][Math]::Round($TimeLeft / 60,[MidpointRounding]::AwayFromZero) + } + $Message = $Message -replace "%", $TimerText + $Success = Send-Command -Command $Warnings.CmdMessage -Message $Message + if ($Success) { + Write-ServerMsg "Waiting $Timer seconds before next warning..." + Start-Sleep -Seconds $Timer + } else { + Write-Warning "Unable to send restart warning." + break + } + } + if (-not ($null -eq $Warnings.CmdSave)){ + Write-ServerMsg "Saving server." + $Success = Send-Command -Command $Warnings.CmdSave + if ($Success) { + Start-Sleep -Seconds $Warnings.SaveDelay + } else { + Write-Warning "Unable to send save command." + } + } + Write-ServerMsg "Closing server." + $Stopped = Send-Command -Command $Warnings.CmdStop + Start-Sleep -Seconds 5 + if (-Not ($Stopped)) { + $Stopped = Stop-Server -ServerProcess $ServerProcess + } + return $Stopped +} + +Export-ModuleMember -Function Send-RestartWarning \ No newline at end of file diff --git a/functions/Stop-Server.psm1 b/functions/Stop-Server.psm1 new file mode 100644 index 0000000..4575312 --- /dev/null +++ b/functions/Stop-Server.psm1 @@ -0,0 +1,33 @@ +function Stop-Server { + [CmdletBinding()] + [OutputType([boolean])] + param ( + [Parameter(Mandatory)] + $ServerProcess + ) + if(-not $Server.HasExited){ + Write-ServerMsg "Closing main window..." + $ServerProcess.CloseMainWindow() + $ServerProcess.WaitForExit(30000) + if ($ServerProcess.HasExited) { + Write-ServerMsg "Server succesfully stopped." + }else{ + Write-Warning "Trying again to stop the server..." + Stop-Process $ServerProcess + $ServerProcess.WaitForExit(30000) + if ($ServerProcess.HasExited) { + Write-Warning "Server succesfully stopped on second try." + }else{ + Write-Warning "Forcefully stopping server..." + Stop-Process $ServerProcess -Force + } + } + } + Start-Sleep -Seconds 5 + if ($ServerProcess.HasExited) { + return $true + } else { + return $false + } +} +Export-ModuleMember -Function Stop-Server \ No newline at end of file diff --git a/functions/Update-Server.psm1 b/functions/Update-Server.psm1 new file mode 100644 index 0000000..c589146 --- /dev/null +++ b/functions/Update-Server.psm1 @@ -0,0 +1,29 @@ +function Update-Server { + [CmdletBinding()] + param ( + [Parameter(Mandatory)] + $UpdateType + ) + + if (-not(Test-Path -Path $Server.Path)){ + New-Item -ItemType "directory" -Path $Server.Path -ErrorAction SilentlyContinue + } + $Server.Path = Resolve-Path -Path $Server.Path + if($Server.Beta){ + Write-ServerMsg "$UpdateType Beta Build." + try { + $Task = Start-Process $Global.SteamCMD -ArgumentList "+@ShutdownOnFailedCommand 1 +@NoPromptForPassword 1 +login anonymous +force_install_dir $($Server.Path) `"+app_update $($Server.AppID) -beta $($Server.BetaBuild) -betapassword $($Server.BetaBuildPassword)`" -validate +quit" -Wait -PassThru -NoNewWindow + } catch { + Exit-WithError -ErrorMsg "SteamCMD failed to complete." + } + } else { + Write-ServerMsg "$UpdateType Regular Build." + try { + $Task = Start-Process $Global.SteamCMD -ArgumentList "+@ShutdownOnFailedCommand 1 +@NoPromptForPassword 1 +login anonymous +force_install_dir $($Server.Path) +app_update $($Server.AppID) -validate +quit" -Wait -PassThru -NoNewWindow + } catch { + Exit-WithError -ErrorMsg "SteamCMD failed to complete." + } + } + $Server.Exec = Resolve-Path -Path $Server.Exec +} +Export-ModuleMember -Function Update-Server \ No newline at end of file diff --git a/functions/Write-ScriptMsg.psm1 b/functions/Write-ScriptMsg.psm1 new file mode 100644 index 0000000..d6eb034 --- /dev/null +++ b/functions/Write-ScriptMsg.psm1 @@ -0,0 +1,10 @@ +function Write-ScriptMsg { + [CmdletBinding()] + param ( + [Parameter(Mandatory)] + [string]$Message + ) + Write-Host -ForegroundColor $Global.SectionColor -BackgroundColor $Global.BgColor -Object $Message +} + +Export-ModuleMember -Function Write-ScriptMsg \ No newline at end of file diff --git a/functions/Write-ServerMsg.psm1 b/functions/Write-ServerMsg.psm1 new file mode 100644 index 0000000..fba0ba7 --- /dev/null +++ b/functions/Write-ServerMsg.psm1 @@ -0,0 +1,10 @@ +function Write-ServerMsg { + [CmdletBinding()] + param ( + [Parameter(Mandatory)] + [string]$Message + ) + Write-Host -ForegroundColor $Global.FGColor -BackgroundColor $Global.BgColor -Object $Message +} + +Export-ModuleMember -Function Write-ServerMsg \ No newline at end of file diff --git a/main.ps1 b/main.ps1 index e1eef42..d811a0c 100644 --- a/main.ps1 +++ b/main.ps1 @@ -5,35 +5,40 @@ [CmdletBinding()] param ( [Parameter(Mandatory)] - [string] - $ServerCfg + [string]$ServerCfg ) -#Console Output Text Color -[string]$FgColor="Green" - -#Console Output Text Color for sections -[string]$SectionColor="Blue" +#--------------------------------------------------------- +# Importing functions and variables. +#--------------------------------------------------------- -#Console Output Background Color -[string]$BgColor="Black" +try { + Import-Module -Name ".\configs\global.psm1" + Get-ChildItem -Path ".\functions" -Include "*.psm1" -Recurse | Import-Module + Import-Module -Name ".\configs\$ServerCfg.psm1" +} +catch { + Exit-WithError -ErrorMsg "Unable to import modules." + exit +} #--------------------------------------------------------- # Set Script Directory as Working Directory -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Setting Working Directory..." #--------------------------------------------------------- -$scriptpath=$MyInvocation.MyCommand.Path -$dir=Split-Path -Path $scriptpath -$dir=Resolve-Path -Path $dir +Write-ScriptMsg "Setting Script Directory as Working Directory..." +$scriptpath = $MyInvocation.MyCommand.Path +$dir = Split-Path -Path $scriptpath +$dir = Resolve-Path -Path $dir Set-Location -Path $dir +Write-ScriptMsg "Working Directory : $(Get-Location)" #--------------------------------------------------------- -# Get server local IP -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Getting server local IP..." +# Get server IPs #--------------------------------------------------------- -$ServerIP = ( +Write-ScriptMsg "Finding server IPs..." +$ServerInternalIP = ( Get-NetIPConfiguration | Where-Object { $_.IPv4DefaultGateway -ne $null -and @@ -41,74 +46,38 @@ $ServerIP = ( } ).IPv4Address.IPAddress -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Server local IP : $ServerIP" +$ServerExternalIP = (Invoke-WebRequest ifconfig.me/ip).Content.Trim() -#--------------------------------------------------------- -# Import Functions and Modules -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Importing modules..." -#--------------------------------------------------------- +Write-ScriptMsg "Server local IP : $ServerInternalIP" +Write-ScriptMsg "Server external IP : $ServerExternalIP" -# Core Function -try { - Get-ChildItem -Path ".\functions" -Include "*.psm1" -Recurse | Import-Module -} -catch { - Exit-WithError -ErrorMsg "Unable to import functions." -} - -# Modules -try { - Get-ChildItem -Path ".\Modules" -Include "*.psm1" -Recurse | Import-Module -} -catch { - Exit-WithError -ErrorMsg "Unable to import module." -} - -#--------------------------------------------------------- -# Import Variables -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Importing functions and variables from $ServerCfg ..." -#--------------------------------------------------------- - -# Global Variables -try { - Import-Module -Name ".\configs\global.psm1" -} -catch { - Exit-WithError -ErrorMsg "Unable to import global configuration." -} - -# Server Variables and Functions -try { - Import-Module -Name ".\configs\$ServerCfg.psm1" -} -catch { - Exit-WithError -ErrorMsg "Unable to import server configuration." -} +Add-Member -InputObject $Global -Name "ServerInternalIP" -Type NoteProperty -Value $ServerInternalIP +Add-Member -InputObject $Global -Name "ServerExternalIP" -Type NoteProperty -Value $ServerExternalIP #--------------------------------------------------------- # Start Logging #--------------------------------------------------------- -$LogFile="$(Get-TimeStamp).txt" +$LogFile = "$(Get-TimeStamp).txt" # Start Logging -Start-Transcript -Path "$LogFolder\$LogFile" -IncludeInvocationHeader +Start-Transcript -Path "$($Global.LogFolder)\$LogFile" -IncludeInvocationHeader #--------------------------------------------------------- # Install Dependencies -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Verifying Dependencies..." #--------------------------------------------------------- -[Hashtable]$Dependencies=@{ - SevenZip=$SevenZip - Mcrcon=$Mcrcon - SteamCMD=$SteamCMD +Write-ScriptMsg "Verifying Dependencies..." +$Dependencies = @{ + SevenZip = $Global.SevenZip + Mcrcon = $Global.Mcrcon + SteamCMD = $Global.SteamCMD } -[System.Collections.ArrayList]$MissingDependencies=@() +[System.Collections.ArrayList]$MissingDependencies = @() foreach ($Key in $Dependencies.keys) { - if (!(Test-Path $Dependencies[$Key])) { - $null=$MissingDependencies.Add($Key) + if (-not(Test-Path -Path $Dependencies[$Key])) { + $null = $MissingDependencies.Add($Key) } } @@ -117,7 +86,7 @@ if ($MissingDependencies.Count -gt 0){ New-Item -Path ".\downloads" -ItemType "directory" -ErrorAction SilentlyContinue foreach ($Item in $MissingDependencies) { - $Cmd="Install-$Item" + $Cmd = "Install-$Item" &$Cmd -Application $Dependencies[$Item] } @@ -127,72 +96,79 @@ if ($MissingDependencies.Count -gt 0){ #--------------------------------------------------------- # Install Server -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Verifying Server installation..." #--------------------------------------------------------- -[boolean]$FreshInstall=$false -if (!(Test-Path $ServerExec)){ - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server is not installed : Installing $ServerName Server." - Update-Server -ServerPath $ServerPath -SteamCMD $SteamCMD -SteamAppID $SteamAppID -Beta $Beta -BetaBuild $BetaBuild -BetaBuildPassword $BetaBuildPassword -UpdateType "Installing" - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server successfully installed." - $FreshInstall=$true +Write-ScriptMsg "Verifying Server installation..." +[boolean]$FreshInstall = $false +if (-not(Test-Path -Path $Server.Exec)){ + Write-ServerMsg "Server is not installed : Installing $($Server.Name) Server." + Update-Server -UpdateType "Installing" + Write-ServerMsg "Server successfully installed." + $FreshInstall = $true } #--------------------------------------------------------- # If Server is running warn players then stop server -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Verifying Server State..." #--------------------------------------------------------- -If ($UseWarnings -and !$FreshInstall) { - Send-RestartWarning -ProcessName $ProcessName -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -RestartTimers $RestartTimers -RestartMessageMinutes $RestartMessageMinutes -RestartMessageSeconds $RestartMessageSeconds -MessageCmd $MessageCmd -ServerStopCmd $ServerStopCmd -ServerSaveCmd $ServerSaveCmd -Protocol $Protocol +$ServerProcess = Get-Process $Server.ProcessName -ErrorAction SilentlyContinue +Write-ScriptMsg "Verifying Server State..." +if (-not ($ServerProcess) -or $ServerProcess.HasExited) { + Write-ServerMsg "Server is not running." } else { - $Server=Get-Process $ProcessName -ErrorAction SilentlyContinue - $Stopped=Stop-Server -Server $Server + if ($Warnings.Use -and -not ($FreshInstall)) { + Write-ServerMsg "Server is running, warning users about upcomming restart." + $Stopped = Send-RestartWarning -ServerProcess $ServerProcess + } else { + Write-ServerMsg "Server is running, stopping server." + $Stopped = Stop-Server -ServerProcess $ServerProcess + } if ($Stopped) { - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server closed." + Write-ServerMsg "Server stopped." } else { - Exit-WithError -ErrorMsg "Unable to stop server." + Exit-WithError "Unable to stop server." } } #--------------------------------------------------------- # Backup -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Verifying Backups..." #--------------------------------------------------------- -if ($UseBackups -and !$FreshInstall) { - Backup-Server -BackupPath $BackupPath -ServerSaves $ServerSaves -SevenZip $SevenZip -BackupDays $BackupDays -BackupWeeks $BackupWeeks +if ($Backups.Use -and -not ($FreshInstall)) { + Write-ScriptMsg "Verifying Backups..." + Backup-Server } #--------------------------------------------------------- # Update -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Updating Server..." #--------------------------------------------------------- -if (!$FreshInstall) { - #Update-Server -ServerPath $ServerPath -SteamCMD $SteamCMD -SteamAppID $SteamAppID -Beta $Beta -BetaBuild $BetaBuild -BetaBuildPassword $BetaBuildPassword -UpdateType "Updating" - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server successfully updated and/or verified." +if (-not ($FreshInstall)) { + Write-ScriptMsg "Updating Server..." + Update-Server -UpdateType "Updating / Verifying" + Write-ServerMsg "Server successfully updated and/or verified." } #--------------------------------------------------------- # Start Server -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Starting Server..." #--------------------------------------------------------- try { + Write-ScriptMsg "Starting Server..." Start-Server } catch { + Write-Error $_ Exit-WithError -ErrorMsg "Unable to start server." } #--------------------------------------------------------- # Cleanup -Write-Host -ForegroundColor $SectionColor -BackgroundColor $BgColor -Object "Cleaning old logs..." #--------------------------------------------------------- try { - Remove-OldLog -LogFolder $LogFolder -Days 30 + Write-ScriptMsg "Deleting logs older than $($Global.Days) days." + Remove-OldLog } catch { Exit-WithError -ErrorMsg "Unable clean old logs." @@ -202,7 +178,7 @@ catch { # Stop Logging #--------------------------------------------------------- -Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Script successfully completed." +Write-ServerMsg "Script successfully completed." Stop-Transcript diff --git a/modules/Backup-Server.psm1 b/modules/Backup-Server.psm1 deleted file mode 100644 index 30ddd7b..0000000 --- a/modules/Backup-Server.psm1 +++ /dev/null @@ -1,45 +0,0 @@ -function Backup-Server { - [CmdletBinding()] - param ( - [Parameter(Mandatory=$true)] - [string]$BackupPath, - [string]$ServerSaves, - [string]$SevenZip, - [Parameter(Mandatory=$false)] - [int32]$BackupDays=7, - [int32]$BackupWeeks=4 - ) - $SevenZip=Resolve-Path -Path $SevenZip - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Creating Backup." - #Create backup name from date and time - $BackupName=Get-TimeStamp - #Check if it's friday (Sunday is 0) - if ((Get-Date -UFormat %u) -eq 5){ - $Type="Weekly" - $Limit=(Get-Date).AddDays(-$BackupWeeks) - } else { - $Type="Daily" - $Limit=(Get-Date).AddDays(-$BackupDays) - } - #Check if directory exist and create it. - if (!(Test-Path "$BackupPath\$Type" -PathType "Container")){ - New-Item -Path $BackupPath\$Type -ItemType "directory" -ErrorAction SilentlyContinue - } - #Wait for server to have unlocked files - Start-Sleep -Seconds 5 - #Run Backup - try { - & $SevenZip a -tzip -mx=1 $BackupPath\$Type\$BackupName.zip $ServerSaves - } - catch { - Exit-WithError -ErrorMsg "Unable to backup server." - } - - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Backup Created : $BackupName.zip" - - #Delete old backups - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Deleting old backups." - Get-ChildItem -Path $BackupPath\$Type -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.LastWriteTime -lt $Limit } | Remove-Item -Force -} - -Export-ModuleMember -Function Backup-Server \ No newline at end of file diff --git a/modules/Send-RestartWarning.psm1 b/modules/Send-RestartWarning.psm1 deleted file mode 100644 index 57ae7a0..0000000 --- a/modules/Send-RestartWarning.psm1 +++ /dev/null @@ -1,136 +0,0 @@ -function Send-Command { - [CmdletBinding()] - [OutputType([boolean])] - param ( - [Parameter(Mandatory)] - [string]$Mcrcon, - [string]$RconIP, - [int32]$RconPort, - [string]$RconPassword, - [string]$Command - ) - $Task=Start-Process $Mcrcon -ArgumentList "-c -H $RconIP -P $RconPort -p $RconPassword `"$Command`"" -Wait -PassThru -NoNewWindow - if ($Task.ExitCode -eq 0) { - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Command Sent." - return $true - } else { - Write-Warning "Unable to send command" - return $false - } -} - -function Send-TelnetCommand { - [CmdletBinding()] - [OutputType([boolean])] - param ( - [Parameter(Mandatory)] - [string]$RconIP, - [int32]$RconPort, - [string]$RconPassword, - [string]$Command - ) - $Result=Get-Telnet -Command $Command -RemoteHost $RconIP -Port $RconPort -Password $RconPassword - Write-Host $Result - if (($Result -like "*Unable to connect to host:*") -or ($Result -like "*incorrect*")) { - Write-Warning "Unable to send command." - return $false - } else { - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Command Sent." - return $true - } -} - -function Send-RestartWarning { - [CmdletBinding()] - param ( - [Parameter(Mandatory=$true)] - [string]$ProcessName, - [string]$Mcrcon, - [string]$RconIP, - [int32]$RconPort, - [string]$RconPassword, - [System.Collections.ArrayList]$RestartTimers, - [string]$RestartMessageMinutes, - [string]$RestartMessageSeconds, - [string]$MessageCmd, - [string]$ServerStopCmd, - [Parameter(Mandatory=$false)] - [string]$ServerSaveCmd=$null, - [string]$protocol="RCON" - ) - $Server=Get-Process $ProcessName -ErrorAction SilentlyContinue - $exited=$false - while ($RestartTimers.Count -gt 0) { - $Timer=$RestartTimers[0] - if (!$server -or $Server.HasExited) { - $exited=$true - Write-Warning "Server is not running." - break - } - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server is running, warning users about upcomming restart." - $TimeLeft=0 - $RestartTimers | ForEach-Object { $TimeLeft += $_} - $RestartTimers.RemoveAt(0) - if ($TimeLeft -lt 60) { - $Message=$RestartMessageSeconds - $TimerText=[string]$TimeLeft - } else { - $Message=$RestartMessageMinutes - $TimerText=[string][Math]::Round($TimeLeft / 60,[MidpointRounding]::AwayFromZero) - } - $Message=$Message -replace "%", $TimerText - if ($protocol -eq "RCON"){ - $Command="$MessageCmd $Message" - $Success=Send-Command -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $Command - } - if ($protocol -eq "Telnet"){ - $Command="$MessageCmd `"$Message`"" - $Success=Send-TelnetCommand -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $Command - } - if ($Success) { - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Waiting $Timer seconds before next warning..." - Start-Sleep -Seconds $Timer - } else { - Write-Warning "Unable to send server reboot warning." - break - } - } - if (!$exited){ - if (-not ($ServerSaveCmd -eq $null)){ - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Saving server." - if ($protocol -eq "RCON"){ - $Success=Send-Command -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerSaveCmd - } - if ($protocol -eq "Telnet"){ - $Success=Send-TelnetCommand -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerSaveCmd - } - if ($Success) { - Start-Sleep -Seconds 5 - } else { - Write-Warning "Unable to send server save command." - } - } - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Closing server." - if ($protocol -eq "RCON"){ - $Success=Send-Command -Mcrcon $Mcrcon -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerStopCmd - } - if ($protocol -eq "Telnet"){ - $Success=Send-TelnetCommand -RconIP $RconIP -RconPort $RconPort -RconPassword $RconPassword -Command $ServerStopCmd - } - if ($Success) { - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server closed." - Start-Sleep -Seconds 5 - } else { - Write-Warning "Unable to send server stop command." - $Stopped=Stop-Server -Server $Server - if ($Stopped) { - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server closed." - } else { - Exit-WithError -ErrorMsg "Unable to stop server." - } - } - - } -} - -Export-ModuleMember -Function Send-RestartWarning \ No newline at end of file diff --git a/modules/Stop-Server.psm1 b/modules/Stop-Server.psm1 deleted file mode 100644 index 99792c9..0000000 --- a/modules/Stop-Server.psm1 +++ /dev/null @@ -1,33 +0,0 @@ -function Stop-Server { - param ( - $Server - ) - if(-not $Server.HasExited){ - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Closing Main Windows..." - $Server.CloseMainWindow() - $Server.WaitForExit(30000) - Start-Sleep -Seconds 5 - if ($Server.HasExited) { - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server succesfully shutdown." - }else{ - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Trying again to stop the Server..." - #Try Again - Stop-Process $Server - Start-Sleep -Seconds 5 - if ($Server.HasExited) { - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Server succesfully shutdown on second try." - }else{ - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "Forcing server shutdown..." - #Force Stop - Stop-Process $Server -Force - } - } - } - Start-Sleep -Seconds 5 - if ($Server.HasExited) { - return $true - } else { - return $false - } -} -Export-ModuleMember -Function Stop-Server \ No newline at end of file diff --git a/modules/Update-Server.psm1 b/modules/Update-Server.psm1 deleted file mode 100644 index 11059a4..0000000 --- a/modules/Update-Server.psm1 +++ /dev/null @@ -1,36 +0,0 @@ -function Update-Server { - [CmdletBinding()] - param ( - [Parameter(Mandatory=$true)] - [string]$ServerPath, - [string]$SteamCMD, - [int32]$SteamAppID, - [boolean]$Beta, - - [Parameter(Mandatory=$false)] - [string]$BetaBuild, - [string]$BetaBuildPassword, - [string]$UpdateType - ) - - if (!(Test-Path $ServerPath)){ - New-Item -ItemType "directory" -Path $ServerPath -ErrorAction SilentlyContinue - } - $ServerPath=Resolve-Path -Path $ServerPath - if($Beta){ - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "$UpdateType Beta Build." - try { - $Task=Start-Process $SteamCMD -ArgumentList "+@ShutdownOnFailedCommand 1 +@NoPromptForPassword 1 +login anonymous +force_install_dir $ServerPath `"+app_update $SteamAppID -beta $BetaBuild -betapassword $BetaBuildPassword`" -validate +quit" -Wait -PassThru -NoNewWindow - } catch { - Exit-WithError -ErrorMsg "SteamCMD failed to complete." - } - } else { - Write-Host -ForegroundColor $FgColor -BackgroundColor $BgColor -Object "$UpdateType Regular Build." - try { - $Task=Start-Process $SteamCMD -ArgumentList "+@ShutdownOnFailedCommand 1 +@NoPromptForPassword 1 +login anonymous +force_install_dir $ServerPath +app_update $SteamAppID -validate +quit" -Wait -PassThru -NoNewWindow - } catch { - Exit-WithError -ErrorMsg "SteamCMD failed to complete." - } - } -} -Export-ModuleMember -Function Update-Server \ No newline at end of file diff --git a/run.cmd b/run.cmd index 66696b7..a644f5f 100644 --- a/run.cmd +++ b/run.cmd @@ -1 +1 @@ -start powershell.exe -noprofile -executionpolicy bypass -file ".\main.ps1" -ServerCfg "7daystodie" \ No newline at end of file +start powershell.exe -noprofile -executionpolicy bypass -file ".\main.ps1" -ServerCfg "projectzomboid" \ No newline at end of file From 778e1e69a1e321c443e009c145e7d3d8986778ce Mon Sep 17 00:00:00 2001 From: Patrick Veilleux Date: Sat, 28 Aug 2021 18:41:18 -0400 Subject: [PATCH 7/8] tested --- configs/7daystodie.psm1 | 2 +- configs/projectzomboid.psm1 | 6 +++--- functions/Send-RestartWarning.psm1 | 2 +- functions/Stop-Server.psm1 | 2 +- main.ps1 | 16 ++++++++-------- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/configs/7daystodie.psm1 b/configs/7daystodie.psm1 index 89d54a5..e6eda82 100644 --- a/configs/7daystodie.psm1 +++ b/configs/7daystodie.psm1 @@ -66,7 +66,7 @@ $ServerDetails = @{ Core 6 = > 00100000 = > 32 Core 7 = > 01000000 = > 64 Core 8 = > 10000000 = > 128 - = = = = = = = = = = = = = = = = = = = = = = = = = = + ---------------------------- 8 Cores = > 11111111 = > 255 4 Cores = > 00001111 = > 15 2 Cores = > 00000011 = > 3 diff --git a/configs/projectzomboid.psm1 b/configs/projectzomboid.psm1 index c1668f4..11ac0fd 100644 --- a/configs/projectzomboid.psm1 +++ b/configs/projectzomboid.psm1 @@ -89,7 +89,7 @@ $ServerDetails = @{ Core 6 = > 00100000 = > 32 Core 7 = > 01000000 = > 64 Core 8 = > 10000000 = > 128 - = = = = = = = = = = = = = = = = = = = = = = = = = = + ---------------------------- 8 Cores = > 11111111 = > 255 4 Cores = > 00001111 = > 15 2 Cores = > 00000011 = > 3 @@ -131,7 +131,7 @@ $WarningsDetails = @{ Use = $true #What protocol to use : Rcon, Telnet, Websocket - Protocol = "Telnet" + Protocol = "Rcon" #Times at which the servers will warn the players that it is about to restart. (in seconds between each timers) Timers = [System.Collections.ArrayList]@(240,50,10) #Total wait time is 240+50+10 = 300 seconds or 5 minutes @@ -165,7 +165,7 @@ $Warnings = New-Object -TypeName PsObject -Property $WarningsDetails $PZ_CLASSPATH = "java/jinput.jar;java/lwjgl.jar;java/lwjgl_util.jar;java/sqlite-jdbc-3.8.10.1.jar;java/trove-3.0.3.jar;java/uncommons-maths-1.2.3.jar;java/javacord-2.0.17-shaded.jar;java/guava-23.0.jar;java/" #Launch Arguments -$ArgumentList = "-Dzomboid.steam = 1 -Dzomboid.znetlog = 1 -XX:+UseConcMarkSweepGC -XX:-CreateMinidumpOnCrash -XX:-OmitStackTraceInFastThrow -Xms2048m -Xmx2048m -Djava.library.path = natives/;. -cp $PZ_CLASSPATH zombie.network.GameServer" +$ArgumentList = "-Dzomboid.steam=1 -Dzomboid.znetlog=1 -XX:+UseConcMarkSweepGC -XX:-CreateMinidumpOnCrash -XX:-OmitStackTraceInFastThrow -Xms2048m -Xmx2048m -Djava.library.path=natives/;. -cp $PZ_CLASSPATH zombie.network.GameServer" $Launcher = "$($Server.Path)\jre64\bin\java.exe" diff --git a/functions/Send-RestartWarning.psm1 b/functions/Send-RestartWarning.psm1 index c183340..a4e795c 100644 --- a/functions/Send-RestartWarning.psm1 +++ b/functions/Send-RestartWarning.psm1 @@ -39,7 +39,7 @@ function Send-RestartWarning { } Write-ServerMsg "Closing server." $Stopped = Send-Command -Command $Warnings.CmdStop - Start-Sleep -Seconds 5 + Start-Sleep -Seconds 10 if (-Not ($Stopped)) { $Stopped = Stop-Server -ServerProcess $ServerProcess } diff --git a/functions/Stop-Server.psm1 b/functions/Stop-Server.psm1 index 4575312..06a7d25 100644 --- a/functions/Stop-Server.psm1 +++ b/functions/Stop-Server.psm1 @@ -23,7 +23,7 @@ function Stop-Server { } } } - Start-Sleep -Seconds 5 + Start-Sleep -Seconds 10 if ($ServerProcess.HasExited) { return $true } else { diff --git a/main.ps1 b/main.ps1 index d811a0c..652ef92 100644 --- a/main.ps1 +++ b/main.ps1 @@ -22,6 +22,14 @@ catch { exit } +#--------------------------------------------------------- +# Start Logging +#--------------------------------------------------------- + +$LogFile = "$(Get-TimeStamp).txt" +# Start Logging +Start-Transcript -Path "$($Global.LogFolder)\$LogFile" -IncludeInvocationHeader + #--------------------------------------------------------- # Set Script Directory as Working Directory #--------------------------------------------------------- @@ -54,14 +62,6 @@ Write-ScriptMsg "Server external IP : $ServerExternalIP" Add-Member -InputObject $Global -Name "ServerInternalIP" -Type NoteProperty -Value $ServerInternalIP Add-Member -InputObject $Global -Name "ServerExternalIP" -Type NoteProperty -Value $ServerExternalIP -#--------------------------------------------------------- -# Start Logging -#--------------------------------------------------------- - -$LogFile = "$(Get-TimeStamp).txt" -# Start Logging -Start-Transcript -Path "$($Global.LogFolder)\$LogFile" -IncludeInvocationHeader - #--------------------------------------------------------- # Install Dependencies #--------------------------------------------------------- From c9d132f3b6a61f3db3655f75b4f773b1d30218ee Mon Sep 17 00:00:00 2001 From: Patrick Veilleux Date: Sat, 28 Aug 2021 18:49:16 -0400 Subject: [PATCH 8/8] faster shutdown on failed rcon --- functions/Send-RestartWarning.psm1 | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/functions/Send-RestartWarning.psm1 b/functions/Send-RestartWarning.psm1 index a4e795c..6bdca40 100644 --- a/functions/Send-RestartWarning.psm1 +++ b/functions/Send-RestartWarning.psm1 @@ -6,6 +6,7 @@ function Send-RestartWarning { $ServerProcess ) $Stopped = $false + $Failed = $false while ($Warnings.Timers.Count -gt 0) { $Timer = $Warnings.Timers[0] $TimeLeft = 0 @@ -25,23 +26,26 @@ function Send-RestartWarning { Start-Sleep -Seconds $Timer } else { Write-Warning "Unable to send restart warning." + $Failed = $true break } } - if (-not ($null -eq $Warnings.CmdSave)){ - Write-ServerMsg "Saving server." - $Success = Send-Command -Command $Warnings.CmdSave - if ($Success) { - Start-Sleep -Seconds $Warnings.SaveDelay - } else { - Write-Warning "Unable to send save command." + if (-not ($Failed)) { + if (-not ($null -eq $Warnings.CmdSave)){ + Write-ServerMsg "Saving server." + $Success = Send-Command -Command $Warnings.CmdSave + if ($Success) { + Start-Sleep -Seconds $Warnings.SaveDelay + } else { + Write-Warning "Unable to send save command." + } + } + Write-ServerMsg "Closing server." + $Stopped = Send-Command -Command $Warnings.CmdStop + Start-Sleep -Seconds 10 + if (-Not ($Stopped)) { + $Stopped = Stop-Server -ServerProcess $ServerProcess } - } - Write-ServerMsg "Closing server." - $Stopped = Send-Command -Command $Warnings.CmdStop - Start-Sleep -Seconds 10 - if (-Not ($Stopped)) { - $Stopped = Stop-Server -ServerProcess $ServerProcess } return $Stopped }