Files
Abiotic-Factor-Server-Manager/AFSM.ps1
T
2026-05-10 15:36:56 +00:00

710 lines
28 KiB
PowerShell

# Abiotic Factor Server Manager
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$configPath = "$scriptDir\server_config.json"
$script:serverProcess = $null
$script:configChanged = $false
# Get local IP address
function Get-LocalIP {
$ip = Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -notlike "*Loopback*" -and $_.InterfaceAlias -notlike "*Virtual*" -and $_.IPAddress -notlike "169.254.*" } | Select-Object -First 1
if ($ip) { return $ip.IPAddress }
return "127.0.0.1"
}
# Get public IP (WAN)
function Get-PublicIP {
try {
$wanIP = (Invoke-WebRequest -Uri "https://api.ipify.org" -UseBasicParsing -TimeoutSec 3).Content
return $wanIP
} catch {
return "Unavailable"
}
}
# Load/Save Config
function Load-Config {
if (Test-Path $configPath) {
try {
$cfg = Get-Content $configPath -Raw | ConvertFrom-Json
$txtSteamCMDDir.Text = $cfg.SteamCMDDir
$txtInstallDir.Text = $cfg.InstallDir
$txtMaxPlayers.Text = $cfg.MaxPlayers
$txtPort.Text = $cfg.Port
$txtQueryPort.Text = $cfg.QueryPort
$txtServerPassword.Text = $cfg.ServerPassword
$txtAdminPassword.Text = $cfg.AdminPassword
$txtServerName.Text = $cfg.ServerName
$script:configChanged = $false
$btnSave.BackColor = [System.Drawing.Color]::FromArgb(240, 240, 240)
} catch {
Set-Defaults
}
} else {
Set-Defaults
}
Update-SteamCMDStatus
Update-GameDirStatus
}
function Set-Defaults {
$txtSteamCMDDir.Text = Join-Path $scriptDir "SteamCMD"
$txtInstallDir.Text = Join-Path $scriptDir "ServerFiles"
$txtMaxPlayers.Text = "6"
$txtPort.Text = "7777"
$txtQueryPort.Text = "27015"
$txtServerPassword.Text = ""
$txtAdminPassword.Text = ""
$txtServerName.Text = "My Abiotic Factor Server"
$script:configChanged = $false
$btnSave.BackColor = [System.Drawing.Color]::FromArgb(240, 240, 240)
}
function Save-Config {
$cfg = @{
SteamCMDDir = $txtSteamCMDDir.Text
InstallDir = $txtInstallDir.Text
MaxPlayers = $txtMaxPlayers.Text
Port = $txtPort.Text
QueryPort = $txtQueryPort.Text
ServerPassword = $txtServerPassword.Text
AdminPassword = $txtAdminPassword.Text
ServerName = $txtServerName.Text
}
$cfg | ConvertTo-Json | Out-File $configPath -Encoding UTF8 -Force
$script:configChanged = $false
$btnSave.BackColor = [System.Drawing.Color]::FromArgb(240, 240, 240)
Update-SteamCMDStatus
Update-GameDirStatus
}
function Mark-ConfigChanged {
if (-not $script:configChanged) {
$script:configChanged = $true
$btnSave.BackColor = [System.Drawing.Color]::LightBlue
}
}
function Update-SteamCMDStatus {
$exe = "$($txtSteamCMDDir.Text)\steamcmd.exe"
if (Test-Path $exe) {
$lblSteamCMDStatus.Text = "SteamCMD: Ready"
$lblSteamCMDStatus.ForeColor = "Green"
$btnInstallSteamCMD.Enabled = $false
$btnInstallSteamCMD.Text = "SteamCMD Installed"
} else {
$lblSteamCMDStatus.Text = "SteamCMD: Not Found"
$lblSteamCMDStatus.ForeColor = "Red"
$btnInstallSteamCMD.Enabled = $true
$btnInstallSteamCMD.Text = "Install SteamCMD"
}
}
function Update-GameDirStatus {
$installDir = $txtInstallDir.Text
if (-not $installDir) {
$lblGameDirStatus.Text = "Game Directory: Not Set"
$lblGameDirStatus.ForeColor = "Red"
return
}
$serverExe = Join-Path $installDir "AbioticFactor\Binaries\Win64\AbioticFactorServer-Win64-Shipping.exe"
if (Test-Path $serverExe) {
$lblGameDirStatus.Text = "Game Directory: Ready"
$lblGameDirStatus.ForeColor = "Green"
} else {
$lblGameDirStatus.Text = "Game Directory: Not Found (Run Update Server)"
$lblGameDirStatus.ForeColor = "Red"
}
}
function Check-ServerSetupComplete {
$installDir = $txtInstallDir.Text
if (-not $installDir) { return $false }
$serverExe = Join-Path $installDir "AbioticFactor\Binaries\Win64\AbioticFactorServer-Win64-Shipping.exe"
return (Test-Path $serverExe)
}
function Install-SteamCMD {
$path = $txtSteamCMDDir.Text
if (-not $path) { return }
if (Test-Path "$path\steamcmd.exe") {
Update-SteamCMDStatus
return
}
New-Item -ItemType Directory -Path $path -Force | Out-Null
$zip = "$env:TEMP\steamcmd.zip"
$wc = New-Object System.Net.WebClient
$wc.DownloadFile("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip", $zip)
$shell = New-Object -ComObject Shell.Application
$shell.NameSpace($zip).Items() | ForEach-Object { $shell.NameSpace($path).CopyHere($_, 16) }
Start-Sleep -Seconds 2
Remove-Item $zip -Force
Update-SteamCMDStatus
Save-Config
}
function Update-Server {
if (-not (Test-Path "$($txtSteamCMDDir.Text)\steamcmd.exe")) {
[System.Windows.Forms.MessageBox]::Show("Please install SteamCMD first!", "Error", "OK", "Error")
return
}
$installDir = $txtInstallDir.Text
if (-not $installDir) {
$installDir = "$($txtSteamCMDDir.Text)\AbioticFactorServer"
$txtInstallDir.Text = $installDir
Save-Config
}
New-Item -ItemType Directory -Path $installDir -Force | Out-Null
$appId = "2857200"
$scriptFile = [System.IO.Path]::GetTempFileName() + ".txt"
$scriptContent = "@ShutdownOnFailedCommand 0`n"
$scriptContent += "@NoPromptForPassword 1`n"
$scriptContent += "force_install_dir `"$installDir`"`n"
$scriptContent += "login anonymous`n"
$scriptContent += "app_update $appId`n"
$scriptContent += "app_update $appId validate`n"
$scriptContent += "quit`n"
$scriptContent | Out-File $scriptFile -Encoding ASCII
$steamCMDExe = "$($txtSteamCMDDir.Text)\steamcmd.exe"
$arguments = "+runscript `"$scriptFile`""
Write-Host "Updating server. Please wait..."
$process = Start-Process -FilePath $steamCMDExe -ArgumentList $arguments -Wait -PassThru -NoNewWindow
$process.WaitForExit()
Start-Sleep -Seconds 2
try {
Remove-Item $scriptFile -Force -ErrorAction SilentlyContinue
} catch {}
Write-Host "Update complete!"
Update-GameDirStatus
[System.Windows.Forms.MessageBox]::Show("Server update completed!", "Success", "OK", "Information")
}
function Start-Server {
if ($script:configChanged) {
$result = [System.Windows.Forms.MessageBox]::Show("You have unsaved configuration changes.`n`nDo you want to save them before starting the server?", "Unsaved Changes", "YesNoCancel", "Question")
if ($result -eq "Cancel") {
return
}
if ($result -eq "Yes") {
Save-Config
}
}
$installDir = $txtInstallDir.Text
if (-not $installDir) {
[System.Windows.Forms.MessageBox]::Show("Please set Game Install Directory first!", "Error", "OK", "Error")
return
}
$serverExe = Join-Path $installDir "AbioticFactor\Binaries\Win64\AbioticFactorServer-Win64-Shipping.exe"
if (-not (Test-Path $serverExe)) {
[System.Windows.Forms.MessageBox]::Show("Server not found! Please run Update Server first.", "Error", "OK", "Error")
return
}
$binariesDir = Join-Path $installDir "AbioticFactor\Binaries\Win64"
$appIdFile = Join-Path $binariesDir "steam_appid.txt"
"2896390" | Out-File -FilePath $appIdFile -Encoding ASCII -Force
$args = "-log -newconsole -useperfthreads -NoAsyncLoadingThread -MaxServerPlayers=$($txtMaxPlayers.Text) -PORT=$($txtPort.Text) -QueryPort=$($txtQueryPort.Text)"
if ($txtServerPassword.Text) { $args += " -ServerPassword=`"$($txtServerPassword.Text)`"" }
if ($txtAdminPassword.Text) { $args += " -AdminPassword=`"$($txtAdminPassword.Text)`"" }
if ($txtServerName.Text) { $args += " -SteamServerName=`"$($txtServerName.Text)`"" }
try {
$script:serverProcess = Start-Process -FilePath $serverExe -ArgumentList $args -WorkingDirectory $binariesDir -PassThru
$btnStop.Enabled = $true
$btnStart.Enabled = $false
$btnUpdate.Enabled = $false
$lblStatusValue.Text = "RUNNING"
$lblStatusValue.ForeColor = "Green"
} catch {
[System.Windows.Forms.MessageBox]::Show("Failed to start server: $_", "Error", "OK", "Error")
}
}
function Stop-Server {
if ($script:serverProcess -and (-not $script:serverProcess.HasExited)) {
$script:serverProcess.Kill()
$script:serverProcess.WaitForExit(3000)
}
Get-Process -Name "AbioticFactorServer-Win64-Shipping" -ErrorAction SilentlyContinue | ForEach-Object {
try { $_.Kill() } catch {}
}
$script:serverProcess = $null
$btnStop.Enabled = $false
$btnStart.Enabled = $true
$btnUpdate.Enabled = $true
$lblStatusValue.Text = "STOPPED"
$lblStatusValue.ForeColor = "Red"
}
function Browse-Directory {
param($txtBox)
$dlg = New-Object System.Windows.Forms.FolderBrowserDialog
if ($dlg.ShowDialog() -eq "OK") {
$txtBox.Text = $dlg.SelectedPath
if ($txtBox.Name -eq "txtSteamCMDDir") { Update-SteamCMDStatus }
if ($txtBox.Name -eq "txtInstallDir") { Update-GameDirStatus }
Mark-ConfigChanged
}
}
function Show-Password {
param($txtBox)
if ($txtBox.PasswordChar -eq '*') {
$txtBox.PasswordChar = $null
} else {
$txtBox.PasswordChar = '*'
}
}
# Create Form
$form = New-Object System.Windows.Forms.Form
$form.Text = "Abiotic Factor Server Manager"
$form.Size = New-Object System.Drawing.Size(920, 780)
$form.StartPosition = "CenterScreen"
$form.MinimumSize = New-Object System.Drawing.Size(920, 780)
$form.MaximumSize = New-Object System.Drawing.Size(920, 780)
$form.FormBorderStyle = "FixedDialog"
$form.MaximizeBox = $false
$stdButtonWidth = 120
$stdButtonHeight = 32
# Status Panel
$statusPanel = New-Object System.Windows.Forms.Panel
$statusPanel.BackColor = [System.Drawing.Color]::FromArgb(240, 240, 240)
$statusPanel.Location = New-Object System.Drawing.Point(0, 0)
$statusPanel.Size = New-Object System.Drawing.Size(920, 100)
$statusPanel.BorderStyle = "FixedSingle"
# Logo/Image Area with embedded image
$logoBox = New-Object System.Windows.Forms.PictureBox
$logoBox.Location = New-Object System.Drawing.Point(15, 15)
$logoBox.Size = New-Object System.Drawing.Size(70, 70)
$logoBox.Width = 70
$logoBox.Height = 70
$logoBox.BackColor = [System.Drawing.Color]::Transparent
$logoBox.BorderStyle = "None"
$logoBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::Zoom
# Embedded image (replace YOUR_BASE64_STRING_HERE with your actual base64 string)
$base64String = "#"
if ($base64String -and $base64String -ne "#") {
$imageBytes = [System.Convert]::FromBase64String($base64String)
$ms = New-Object System.IO.MemoryStream($imageBytes, 0, $imageBytes.Length)
$ms.Write($imageBytes, 0, $imageBytes.Length)
$logoBox.Image = [System.Drawing.Image]::FromStream($ms)
$ms.Close()
}
$statusPanel.Controls.Add($logoBox)
$lblStatusLabel = New-Object System.Windows.Forms.Label
$lblStatusLabel.Text = "Server Status:"
$lblStatusLabel.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
$lblStatusLabel.Location = New-Object System.Drawing.Point(100, 15)
$lblStatusLabel.Size = New-Object System.Drawing.Size(100, 20)
$statusPanel.Controls.Add($lblStatusLabel)
$lblStatusValue = New-Object System.Windows.Forms.Label
$lblStatusValue.Text = "STOPPED"
$lblStatusValue.ForeColor = "Red"
$lblStatusValue.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
$lblStatusValue.Location = New-Object System.Drawing.Point(200, 15)
$lblStatusValue.Size = New-Object System.Drawing.Size(100, 20)
$statusPanel.Controls.Add($lblStatusValue)
$lblServerNameLabel = New-Object System.Windows.Forms.Label
$lblServerNameLabel.Text = "Server Name:"
$lblServerNameLabel.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$lblServerNameLabel.Location = New-Object System.Drawing.Point(100, 40)
$lblServerNameLabel.Size = New-Object System.Drawing.Size(80, 18)
$statusPanel.Controls.Add($lblServerNameLabel)
$lblServerNameValue = New-Object System.Windows.Forms.Label
$lblServerNameValue.Font = New-Object System.Drawing.Font("Segoe UI", 8, [System.Drawing.FontStyle]::Bold)
$lblServerNameValue.Location = New-Object System.Drawing.Point(180, 40)
$lblServerNameValue.Size = New-Object System.Drawing.Size(400, 18)
$lblServerNameValue.AutoEllipsis = $true
$statusPanel.Controls.Add($lblServerNameValue)
$lblPortLabel = New-Object System.Windows.Forms.Label
$lblPortLabel.Text = "Game Port:"
$lblPortLabel.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$lblPortLabel.Location = New-Object System.Drawing.Point(100, 63)
$lblPortLabel.Size = New-Object System.Drawing.Size(70, 18)
$statusPanel.Controls.Add($lblPortLabel)
$lblPortValue = New-Object System.Windows.Forms.Label
$lblPortValue.Text = "7777"
$lblPortValue.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$lblPortValue.Location = New-Object System.Drawing.Point(170, 63)
$lblPortValue.Size = New-Object System.Drawing.Size(60, 18)
$statusPanel.Controls.Add($lblPortValue)
$lblPasswordLabel = New-Object System.Windows.Forms.Label
$lblPasswordLabel.Text = "Password:"
$lblPasswordLabel.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$lblPasswordLabel.Location = New-Object System.Drawing.Point(250, 63)
$lblPasswordLabel.Size = New-Object System.Drawing.Size(65, 18)
$statusPanel.Controls.Add($lblPasswordLabel)
$lblPasswordValue = New-Object System.Windows.Forms.Label
$lblPasswordValue.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$lblPasswordValue.Location = New-Object System.Drawing.Point(315, 63)
$lblPasswordValue.Size = New-Object System.Drawing.Size(80, 18)
$statusPanel.Controls.Add($lblPasswordValue)
$lblLocalLabel = New-Object System.Windows.Forms.Label
$lblLocalLabel.Text = "Local IP:"
$lblLocalLabel.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$lblLocalLabel.Location = New-Object System.Drawing.Point(590, 15)
$lblLocalLabel.Size = New-Object System.Drawing.Size(60, 18)
$statusPanel.Controls.Add($lblLocalLabel)
$lblLocalValue = New-Object System.Windows.Forms.Label
$lblLocalValue.Text = (Get-LocalIP)
$lblLocalValue.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$lblLocalValue.Location = New-Object System.Drawing.Point(650, 15)
$lblLocalValue.Size = New-Object System.Drawing.Size(230, 18)
$statusPanel.Controls.Add($lblLocalValue)
$lblWANLabel = New-Object System.Windows.Forms.Label
$lblWANLabel.Text = "WAN IP:"
$lblWANLabel.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$lblWANLabel.Location = New-Object System.Drawing.Point(590, 40)
$lblWANLabel.Size = New-Object System.Drawing.Size(60, 18)
$statusPanel.Controls.Add($lblWANLabel)
$lblWANValue = New-Object System.Windows.Forms.Label
$lblWANValue.Text = (Get-PublicIP)
$lblWANValue.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$lblWANValue.Location = New-Object System.Drawing.Point(650, 40)
$lblWANValue.Size = New-Object System.Drawing.Size(230, 18)
$statusPanel.Controls.Add($lblWANValue)
$form.Controls.Add($statusPanel)
# Server Controls GroupBox
$controlsGroup = New-Object System.Windows.Forms.GroupBox
$controlsGroup.Text = "Server Controls"
$controlsGroup.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
$controlsGroup.Location = New-Object System.Drawing.Point(15, 110)
$controlsGroup.Size = New-Object System.Drawing.Size(880, 70)
$form.Controls.Add($controlsGroup)
$btnSave = New-Object System.Windows.Forms.Button
$btnSave.Text = "Save Config"
$btnSave.Size = New-Object System.Drawing.Size($stdButtonWidth, $stdButtonHeight)
$btnSave.Location = New-Object System.Drawing.Point(20, 25)
$btnSave.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$btnSave.Add_Click({ Save-Config })
$controlsGroup.Controls.Add($btnSave)
$btnUpdate = New-Object System.Windows.Forms.Button
$btnUpdate.Text = "Update Server"
$btnUpdate.Size = New-Object System.Drawing.Size($stdButtonWidth, $stdButtonHeight)
$btnUpdate.Location = New-Object System.Drawing.Point(155, 25)
$btnUpdate.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$btnUpdate.Add_Click({ Update-Server })
$controlsGroup.Controls.Add($btnUpdate)
$btnStart = New-Object System.Windows.Forms.Button
$btnStart.Text = "Start Server"
$btnStart.Size = New-Object System.Drawing.Size($stdButtonWidth, $stdButtonHeight)
$btnStart.Location = New-Object System.Drawing.Point(290, 25)
$btnStart.BackColor = [System.Drawing.Color]::LightGreen
$btnStart.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$btnStart.Add_Click({ Start-Server })
$controlsGroup.Controls.Add($btnStart)
$btnStop = New-Object System.Windows.Forms.Button
$btnStop.Text = "Stop Server"
$btnStop.Size = New-Object System.Drawing.Size($stdButtonWidth, $stdButtonHeight)
$btnStop.Location = New-Object System.Drawing.Point(425, 25)
$btnStop.BackColor = [System.Drawing.Color]::LightCoral
$btnStop.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$btnStop.Enabled = $false
$btnStop.Add_Click({ Stop-Server })
$controlsGroup.Controls.Add($btnStop)
# Settings Panel
$settingsPanel = New-Object System.Windows.Forms.Panel
$settingsPanel.Location = New-Object System.Drawing.Point(15, 190)
$settingsPanel.Size = New-Object System.Drawing.Size(880, 490)
$settingsPanel.AutoScroll = $true
$form.Controls.Add($settingsPanel)
# SteamCMD Group
$steamCMDGroup = New-Object System.Windows.Forms.GroupBox
$steamCMDGroup.Text = "SteamCMD Configuration"
$steamCMDGroup.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
$steamCMDGroup.Location = New-Object System.Drawing.Point(5, 5)
$steamCMDGroup.Size = New-Object System.Drawing.Size(855, 90)
$settingsPanel.Controls.Add($steamCMDGroup)
$lbl1 = New-Object System.Windows.Forms.Label
$lbl1.Text = "SteamCMD Directory:"
$lbl1.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$lbl1.Location = New-Object System.Drawing.Point(15, 30)
$lbl1.Size = New-Object System.Drawing.Size(135, 22)
$steamCMDGroup.Controls.Add($lbl1)
$txtSteamCMDDir = New-Object System.Windows.Forms.TextBox
$txtSteamCMDDir.Location = New-Object System.Drawing.Point(155, 28)
$txtSteamCMDDir.Size = New-Object System.Drawing.Size(450, 23)
$txtSteamCMDDir.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$txtSteamCMDDir.Name = "txtSteamCMDDir"
$steamCMDGroup.Controls.Add($txtSteamCMDDir)
$btnBrowse1 = New-Object System.Windows.Forms.Button
$btnBrowse1.Text = "Browse"
$btnBrowse1.Location = New-Object System.Drawing.Point(615, 27)
$btnBrowse1.Size = New-Object System.Drawing.Size(90, 26)
$btnBrowse1.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$btnBrowse1.Add_Click({ Browse-Directory $txtSteamCMDDir })
$steamCMDGroup.Controls.Add($btnBrowse1)
$btnInstallSteamCMD = New-Object System.Windows.Forms.Button
$btnInstallSteamCMD.Location = New-Object System.Drawing.Point(715, 27)
$btnInstallSteamCMD.Size = New-Object System.Drawing.Size(125, 26)
$btnInstallSteamCMD.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$btnInstallSteamCMD.Add_Click({ Install-SteamCMD })
$steamCMDGroup.Controls.Add($btnInstallSteamCMD)
$lblSteamCMDStatus = New-Object System.Windows.Forms.Label
$lblSteamCMDStatus.Location = New-Object System.Drawing.Point(155, 60)
$lblSteamCMDStatus.Size = New-Object System.Drawing.Size(450, 20)
$lblSteamCMDStatus.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$steamCMDGroup.Controls.Add($lblSteamCMDStatus)
# Install Dir Group
$installGroup = New-Object System.Windows.Forms.GroupBox
$installGroup.Text = "Game Installation"
$installGroup.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
$installGroup.Location = New-Object System.Drawing.Point(5, 105)
$installGroup.Size = New-Object System.Drawing.Size(855, 90)
$settingsPanel.Controls.Add($installGroup)
$lbl2 = New-Object System.Windows.Forms.Label
$lbl2.Text = "Game Install Directory:"
$lbl2.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$lbl2.Location = New-Object System.Drawing.Point(15, 30)
$lbl2.Size = New-Object System.Drawing.Size(135, 22)
$installGroup.Controls.Add($lbl2)
$txtInstallDir = New-Object System.Windows.Forms.TextBox
$txtInstallDir.Location = New-Object System.Drawing.Point(155, 28)
$txtInstallDir.Size = New-Object System.Drawing.Size(540, 23)
$txtInstallDir.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$installGroup.Controls.Add($txtInstallDir)
$btnBrowse2 = New-Object System.Windows.Forms.Button
$btnBrowse2.Text = "Browse"
$btnBrowse2.Location = New-Object System.Drawing.Point(705, 27)
$btnBrowse2.Size = New-Object System.Drawing.Size(90, 26)
$btnBrowse2.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$btnBrowse2.Add_Click({ Browse-Directory $txtInstallDir })
$installGroup.Controls.Add($btnBrowse2)
$lblGameDirStatus = New-Object System.Windows.Forms.Label
$lblGameDirStatus.Location = New-Object System.Drawing.Point(155, 60)
$lblGameDirStatus.Size = New-Object System.Drawing.Size(540, 20)
$lblGameDirStatus.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$installGroup.Controls.Add($lblGameDirStatus)
# Server Settings Group
$serverGroup = New-Object System.Windows.Forms.GroupBox
$serverGroup.Text = "Server Settings"
$serverGroup.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
$serverGroup.Location = New-Object System.Drawing.Point(5, 205)
$serverGroup.Size = New-Object System.Drawing.Size(855, 185)
$settingsPanel.Controls.Add($serverGroup)
$lblMax = New-Object System.Windows.Forms.Label
$lblMax.Text = "Max Players:"
$lblMax.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$lblMax.Location = New-Object System.Drawing.Point(15, 32)
$lblMax.Size = New-Object System.Drawing.Size(90, 22)
$serverGroup.Controls.Add($lblMax)
$txtMaxPlayers = New-Object System.Windows.Forms.TextBox
$txtMaxPlayers.Location = New-Object System.Drawing.Point(110, 30)
$txtMaxPlayers.Size = New-Object System.Drawing.Size(100, 23)
$txtMaxPlayers.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$serverGroup.Controls.Add($txtMaxPlayers)
$lblPort = New-Object System.Windows.Forms.Label
$lblPort.Text = "Game Port:"
$lblPort.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$lblPort.Location = New-Object System.Drawing.Point(235, 32)
$lblPort.Size = New-Object System.Drawing.Size(80, 22)
$serverGroup.Controls.Add($lblPort)
$txtPort = New-Object System.Windows.Forms.TextBox
$txtPort.Location = New-Object System.Drawing.Point(320, 30)
$txtPort.Size = New-Object System.Drawing.Size(100, 23)
$txtPort.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$serverGroup.Controls.Add($txtPort)
$lblQuery = New-Object System.Windows.Forms.Label
$lblQuery.Text = "Query Port:"
$lblQuery.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$lblQuery.Location = New-Object System.Drawing.Point(445, 32)
$lblQuery.Size = New-Object System.Drawing.Size(85, 22)
$serverGroup.Controls.Add($lblQuery)
$txtQueryPort = New-Object System.Windows.Forms.TextBox
$txtQueryPort.Location = New-Object System.Drawing.Point(535, 30)
$txtQueryPort.Size = New-Object System.Drawing.Size(100, 23)
$txtQueryPort.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$serverGroup.Controls.Add($txtQueryPort)
$lblPassServer = New-Object System.Windows.Forms.Label
$lblPassServer.Text = "Server Password:"
$lblPassServer.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$lblPassServer.Location = New-Object System.Drawing.Point(15, 75)
$lblPassServer.Size = New-Object System.Drawing.Size(115, 22)
$serverGroup.Controls.Add($lblPassServer)
$txtServerPassword = New-Object System.Windows.Forms.TextBox
$txtServerPassword.Location = New-Object System.Drawing.Point(135, 73)
$txtServerPassword.Size = New-Object System.Drawing.Size(200, 23)
$txtServerPassword.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$txtServerPassword.PasswordChar = '*'
$serverGroup.Controls.Add($txtServerPassword)
$btnViewServerPass = New-Object System.Windows.Forms.Button
$btnViewServerPass.Text = "V"
$btnViewServerPass.Location = New-Object System.Drawing.Point(340, 72)
$btnViewServerPass.Size = New-Object System.Drawing.Size(30, 25)
$btnViewServerPass.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$btnViewServerPass.Add_Click({ Show-Password $txtServerPassword })
$serverGroup.Controls.Add($btnViewServerPass)
$lblAdmin = New-Object System.Windows.Forms.Label
$lblAdmin.Text = "Admin Password:"
$lblAdmin.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$lblAdmin.Location = New-Object System.Drawing.Point(410, 75)
$lblAdmin.Size = New-Object System.Drawing.Size(120, 22)
$serverGroup.Controls.Add($lblAdmin)
$txtAdminPassword = New-Object System.Windows.Forms.TextBox
$txtAdminPassword.Location = New-Object System.Drawing.Point(535, 73)
$txtAdminPassword.Size = New-Object System.Drawing.Size(200, 23)
$txtAdminPassword.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$txtAdminPassword.PasswordChar = '*'
$serverGroup.Controls.Add($txtAdminPassword)
$btnViewAdminPass = New-Object System.Windows.Forms.Button
$btnViewAdminPass.Text = "V"
$btnViewAdminPass.Location = New-Object System.Drawing.Point(740, 72)
$btnViewAdminPass.Size = New-Object System.Drawing.Size(30, 25)
$btnViewAdminPass.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$btnViewAdminPass.Add_Click({ Show-Password $txtAdminPassword })
$serverGroup.Controls.Add($btnViewAdminPass)
$lblName = New-Object System.Windows.Forms.Label
$lblName.Text = "Server Name:"
$lblName.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$lblName.Location = New-Object System.Drawing.Point(15, 118)
$lblName.Size = New-Object System.Drawing.Size(115, 22)
$serverGroup.Controls.Add($lblName)
$txtServerName = New-Object System.Windows.Forms.TextBox
$txtServerName.Location = New-Object System.Drawing.Point(135, 116)
$txtServerName.Size = New-Object System.Drawing.Size(650, 23)
$txtServerName.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$serverGroup.Controls.Add($txtServerName)
# Bottom Info Panel (replaces startup popup)
$bottomInfoPanel = New-Object System.Windows.Forms.Panel
$bottomInfoPanel.BackColor = [System.Drawing.Color]::FromArgb(255, 255, 225)
$bottomInfoPanel.Location = New-Object System.Drawing.Point(0, 700)
$bottomInfoPanel.Size = New-Object System.Drawing.Size(920, 50)
$bottomInfoPanel.BorderStyle = "FixedSingle"
$bottomInfoLabel = New-Object System.Windows.Forms.Label
$bottomInfoLabel.Text = "Setup Guide: Set SteamCMD Directory → Install SteamCMD → Set Game Install Directory → Update Server → Configure Settings → Save Config → Start Server"
$bottomInfoLabel.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$bottomInfoLabel.Location = New-Object System.Drawing.Point(10, 5)
$bottomInfoLabel.Size = New-Object System.Drawing.Size(895, 40)
$bottomInfoLabel.TextAlign = "MiddleLeft"
$bottomInfoPanel.Controls.Add($bottomInfoLabel)
$form.Controls.Add($bottomInfoPanel)
# Event handlers
$txtPort.Add_TextChanged({
$lblPortValue.Text = $txtPort.Text
Mark-ConfigChanged
})
$txtServerName.Add_TextChanged({
$lblServerNameValue.Text = $txtServerName.Text
Mark-ConfigChanged
})
$txtServerPassword.Add_TextChanged({
if ($txtServerPassword.Text) {
$lblPasswordValue.Text = "Set"
$lblPasswordValue.ForeColor = "Green"
} else {
$lblPasswordValue.Text = "None"
$lblPasswordValue.ForeColor = "Gray"
}
Mark-ConfigChanged
})
$txtMaxPlayers.Add_TextChanged({ Mark-ConfigChanged })
$txtQueryPort.Add_TextChanged({ Mark-ConfigChanged })
$txtAdminPassword.Add_TextChanged({ Mark-ConfigChanged })
$txtSteamCMDDir.Add_TextChanged({
Mark-ConfigChanged
Update-SteamCMDStatus
})
$txtInstallDir.Add_TextChanged({
Mark-ConfigChanged
Update-GameDirStatus
})
# Initialize display values
$lblPortValue.Text = "7777"
$lblServerNameValue.Text = "My Abiotic Factor Server"
$lblPasswordValue.Text = "None"
$lblPasswordValue.ForeColor = "Gray"
# Load config and check setup (no popups)
Load-Config
# Silently check server setup - updates UI status without popup
$null = Check-ServerSetupComplete
$form.ShowDialog()