ConsoleMaster.ps1

#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# POWERSHELL SCRIPT INFO DECLARATION #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
<#PSScriptInfo
 
.VERSION 1.6.6
 
.GUID ef7e7376-9b7f-455c-83a7-5e4b628e13f8
 
.AUTHOR NovaViper
 
.DESCRIPTION Powershell Script for Managing Java Servers (i.e. Minecraft, Bukkit)
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS java minecraft bukkit server manager
 
.LICENSEURI https://raw.githubusercontent.com/NovaViper/Console-Master/master/LICENSE
 
.PROJECTURI https://github.com/NovaViper/Console-Master/tree/master
 
.RELEASENOTES
https://raw.githubusercontent.com/NovaViper/Console-Master/master/changelog.txt
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.PRIVATEDATA
 
#>


#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# VARIABLE DECLARATION #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
$currentLocation = Split-Path -parent $PSCommandPath
$PSScriptInfo = Test-ScriptFileInfo -Path "$currentLocation\ConsoleMaster.ps1"
$ui = (Get-Host).UI.RawUI
$consoleName = "Console Master"
$consoleVersion = $PSScriptInfo.Version
$consoleServerPrefix = "[" + $consoleName + "]:"
$prefix = "$consoleName $consoleVersion"
$QuitConsole = $false
$configFileName = "config.json"
$SleepTime = 3
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# POWERSHELL CUSTOMIZATION #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
$ui.WindowTitle = "$prefix"
Set-Location $currentLocation
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# FUNCTION DECLARATION #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#

function Set-Up-Console() {
    Clear-Host
    $ui.WindowTitle = $prefix + ": Server Running (Jar: , MC )"
    Write-Host "Welcome To $prefix!!"
    Write-Host ''

    $jarFile = Test-Jar "Please enter the name of the server's .jar file (w/o the extension)"
    $useCustomJarLocation = Confirm-Custom-Jar-Location
    if($useCustomJarLocation -eq 'Y'){
        $jarLocation = Test-Jar-Path "Where is your jar file? (w/o the backslash '\' at the end or begining)" $jarFile
    }else{
        $jarLocation = ''
    }
    $mcVersion = Test-Version "Please enter the Minecraft version your server is using"
    $ramDataType = Test-RAM-Type
    $minRAM = Test-Integer "Please enter your minimum amount of RAM (Random Access Memory) to use"
    $maxRAM = Test-Integer "Please enter your maximum amount of RAM (Random Access Memory) to use"

    $fullRAMMin = -Join ($minRAM, $ramDataType)
    $fullRAMMax = -Join ($maxRAM, $ramDataType)
    $basicInfo = @{
        Jar_File                        = "$jarFile"
        Use_Custom_Location             = "$useCustomJarLocation"
        Custom_Location                 = "$jarLocation"
        Minecraft_Version               = "$mcVersion"
        Ram_Min                         = "-Xmx$fullRAMMin"
        Ram_Max                         = "-Xms$fullRAMMax"
        Server_Options                  = 'nogui'

    }

   New-Item $configFileName -ItemType "file" | Out-Null
   $basicInfo | ConvertTo-Json | Set-Content $configFileName

    Write-Host ""
    Write-Host "Moving to Main Menu..." -BackgroundColor Red
    Start-Sleep -Seconds $SleepTime
    Invoke-Main-Menu
}


function Invoke-Main-Menu() {
    Update-Variables
    Clear-Host
    Write-Host @"
---------------------------------- Main Menu ----------------------------------
 
                    1. Start Server and Ngrok
                    2. Configurations Menu
 
                    3. Exit the Console
 
-------------------------------------------------------------------------------
"@


    $answer = Read-Host "Please Make a Selection"
    switch ($answer) {
        '1' {
            Clear-Host
            Start-Server
        }
        '2' {
            Clear-Host
            Invoke-Settings-Menu
        }
        '3' {
            Exit-Script
        }
        default {
            Invaild-Choice "INVALID CHOICE! PLEASE ENTER ONE OF THE CHOICES LISTED!"
            Invoke-Main-Menu
        }
    }
}

function Start-Server() {
    Test-Use-Custom-Location
    $ui.WindowTitle = $prefix + ": Server Running (Jar: " + $Script:INFO.Jar_File + ", MC " + $Script:INFO.Minecraft_Version + ")"
    Write-Host @"
------------------------------- SERVER LOG START -------------------------------
$consoleServerPrefix Starting Server...
"@

    Write-Host "$consoleServerPrefix Checking for Ngrok process..."
    if (-not(Get-Process -Name ngrok -ErrorAction SilentlyContinue)) {
        Write-Host "$consoleServerPrefix Ngrok Not Running! Starting Ngrok..."
        Start-Process ngrok -argumentlist "tcp 25565" -passthru | Out-Null
        Write-Host "$consoleServerPrefix Ngrok Started!"
    }
    else {
        Write-Host "$consoleServerPrefix Ngrok is Already Running! Skipping Ngrok Startup..."
    }
    Write-Host "$consoleServerPrefix Starting .jar File Now.."

    java $INFO.Ram_Min $INFO.Ram_Max -jar $INFO.Jar_File $INFO.Server_Options

    $ui.WindowTitle = "$consoleServerPrefixServer Stopped (Jar: " + $Script:INFO.Jar_File + ", MC " + $Script:INFO.Minecraft_Version + ")"
    Write-Host "$consoleServerPrefixServer Server Stopped! Check Above For Details!"
    Test-Use-Custom-Location
    Invoke-Ask-Restart
}

function Invoke-Ask-Restart() {
    $answer = Read-Host -Prompt "Would you like to restart the server? (Y)es/(N)o"
    switch ($answer.ToUpper()) {
        'Y' {
            Write-Host "Restarting Server..." -BackgroundColor Red
            Start-Sleep $SleepTime
            Clear-Host
            Start-Server
        }
        'N' {
            Clear-Host
            Confirm-Console-Close
        }
        default {
            Invaild-Choice "INVALID CHOICE! PLEASE ENTER ONE OF THE CHOICES LISTED!"
            Invoke-Ask-Restart
        }
    }
}

function Confirm-Console-Close () {
    $ui.WindowTitle = $prefix + ': Confirm Exit'
    $answer = Read-Host "Ok, would you to close"$consoleName"? (Y)es/(N)o"
    switch ($answer.ToUpper()) {

        'Y' {
            Write-Host ""
            Confirm-Ngrok-Close $true
        }
        'N' {
            Write-Host ""
            Confirm-Ngrok-Close $false
        }
        default {
            Invaild-Choice "INVALID CHOICE! PLEASE ENTER ONE OF THE CHOICES LISTED!"
            Confirm-Console-Close
        }
    }
}


function Confirm-Ngrok-Close([bool]$closeConsole) {
    $answer = Read-Host 'Ok, would you to close Ngrok? (Y)es/(N)o'
    switch ($answer.ToUpper()) {

        'Y' {
            Write-Host ""
            Exit-Console-Ngrok $closeConsole $true
        }
        'N' {
            Write-Host ""
            Exit-Console-Ngrok $closeConsole $false
        }
        default {
            Invaild-Choice "INVALID CHOICE! PLEASE ENTER ONE OF THE CHOICES LISTED!"
            Confirm-Ngrok-Close
        }
    }
}

function Exit-Console-Ngrok([bool]$closeConsole, [bool]$closeNgrok) {

    if (($closeConsole -eq $true) -and ($closeNgrok -eq $true)) {
        Stop-Process -Name ngrok
        Exit-Script
    }
    elseif (($closeConsole -eq $false) -and ($closeNgrok -eq $true)) {
        Stop-Process -Name ngrok
        Resume-Main-Menu
    }
    elseif (($closeConsole -eq $true) -and ($closeNgrok -eq $false)) {
        Exit-Script
    }
    else {
        Resume-Main-Menu
    }
}

function Invoke-Settings-Menu() {
    Clear-Host
    Write-Host @"
-------------------------------- Settings Menu --------------------------------
 
    1. Change Jar - Change the either saved jar file name or location
                    that the script executes
    2. Change Version - Change the saved Minecraft version to match
                        what the jar file uses
    3. RAM Allocation - Set the amount of RAM (Random Access Memory)
                        to reserve to the server [!]
    4. Custom Arguments - Set custom arguments besides the RAM [!!]
    5. Factory Reset - Erase all user defined settings and boot to
                       first-time setup [!!!]
 
    6. Return To Main Menu
 
-------------------------------------------------------------------------------
"@


    $answer = Read-Host "Please Make a Selection"
    switch ($answer) {
        '1' {
            Clear-Host
            Edit-Jar-File
        }
        '2' {
            Clear-Host
            Edit-Minecraft-Version
        }
        '3' {
            Clear-Host
            Edit-RAM
        }
        '4' {
            Clear-Host
            Confirm-Change-Args
        }
        '5' {
            Clear-Host
            Confirm-Factory-Reset
        }
        '6' {Resume-Main-Menu}
        default {
            Invaild-Choice "INVALID CHOICE! PLEASE ENTER ONE OF THE CHOICES LISTED!"
            Invoke-Settings-Menu
        }
    }
}

function Edit-Jar-File() {
    $newJar = Test-Jar "Please enter the new name of the server's .jar file (w/o the extension)"
    $useCustomJarLocation = Confirm-Custom-Jar-Location
    if($useCustomJarLocation -eq 'Y'){
        $jarLocation = Test-Jar-Path "Where is your jar file? (w/o the backslash '\' at the end or begining)" $jarFile
    }else{
        $jarLocation = ''
    }

    Save-Variable "Jar_File" $newJar
    Save-Variable "Custom_Location" $jarLocation
    Save-Variable "Use_Custom_Location" $useCustomJarLocation
    Resume-Settings-Menu
}

function Edit-Minecraft-Version() {
    $newVersion = Test-Version "Please enter the new Minecraft version your server is using"
    Save-Variable "Minecraft_Version" $newVersion
    Resume-Settings-Menu
}

function Edit-RAM() {
    $newRamDataType = Test-RAM-Type
    $newMinRAM = Test-Integer "Please enter your minimum amount of RAM (Random Access Memory) to use"
    $newMaxRAM = Test-Integer "Please enter your maximum amount of RAM (Random Access Memory) to use"

    $newFullMinRAM = -Join ($newMinRAM, $newRamDataType)
    $newFullMaxRAM = -Join ($newMaxRAM, $newRamDataType)
    Save-Variable "Ram_Min" "-Xms$newFullMinRAM"
    Save-Variable "Ram_Max" "-Xmx$newFullMaxRAM"
    Resume-Settings-Menu
}

function Confirm-Change-Args() {
    Write-Host "Here are your original arguments:" $Script:INFO.Server_Options
    $answer = Read-Host "Are you SURE you want to modify these arguments? (Y)es/(N)o"
    switch ($answer.ToUpper()) {

        'Y' {
            Clear-Host
            Edit-Args
        }
        'N' {
            Clear-Host
            Resume-Settings-Menu
        }
        default {
            Invaild-Choice "INVALID CHOICE! PLEASE ENTER ONE OF THE CHOICES LISTED!"
            Confirm-Factory-Reset
        }
    }
}

function Edit-Args() {
    Write-Host "As a refresher, here are your original arguments:" $Script:INFO.Server_Options
    $data = ''
    While (($null -eq $data) -or ($data -eq '')) {
        [string]$data = Read-Host -Prompt "Please enter new arguments for your server"

        if (($null -eq $data) -or ($data -eq '')) {
            Write-Output ''
            $data = ''
            Invaild-Choice "You cannot enter a null/empty name!"
        }
        else {
            Save-Variable "Server_Options" $data
            Resume-Settings-Menu
        }
    }
}

function Confirm-Factory-Reset() {
    Write-Host "Are you sure you want to reset back to factory default? This process CANNOT be reversed!!" -ForegroundColor Red
    $answer = Read-Host "(Y)es or (N)o"
    if (($null -eq $answer) -or ($answer -eq '')) {
        Write-Output ''
        $answer = ''
        Invaild-Choice "You cannot enter a null/empty name!"
        Confirm-Factory-Reset
    }
    else {
        switch ($answer.ToUpper()) {

            'Y' {
                Clear-Host
                Initialize-Factory-Reset
            }
            'N' {
                Clear-Host
                Resume-Settings-Menu
            }
            default {
                Invaild-Choice "INVALID CHOICE! PLEASE ENTER ONE OF THE CHOICES LISTED!"
                Confirm-Factory-Reset
            }
        }
    }
}

function Initialize-Factory-Reset() {
    Write-Host "Deleting Preferences..." -BackgroundColor Red
    Remove-Item $configFileName
    Clear-Variable -name INFO
    Write-Host "Factory Reset Completed!" -ForegroundColor Green
    Write-Host ""
    Write-Host "Returning to First-Time Setup..." -BackgroundColor Red
    Start-Sleep -Seconds $SleepTime
    Set-Up-Console
}


function Exit-Script() {
    Write-Host ""
    Write-Host 'Exiting Script...' -BackgroundColor Red
    Start-Sleep -Seconds $SleepTime
    $QuitConsole = $true
}

function Resume-Main-Menu() {
    Write-Host ""
    Write-Host 'Returning to Main Menu...' -BackgroundColor Red
    Start-Sleep -Seconds $SleepTime
    Invoke-Main-Menu
}

function Resume-Settings-Menu() {
    Write-Host ""
    Write-Host "Returning to Settings Menu..." -BackgroundColor Red
    Start-Sleep -Seconds $SleepTime
    Invoke-Settings-Menu
}

function Invaild-Choice([string]$message) {
    [Console]::Beep(1000, 100)
    Write-Host $message -ForegroundColor Red
    Start-Sleep -Seconds $SleepTime
}

function Update-Variables() {
    $Script:INFO = Get-Content -Path $configFileName -Raw | ConvertFrom-Json
}

function Save-Variable($keyName, $data) {
    $Script:INFO.$keyName = $data
    $Script:INFO | ConvertTo-Json | Set-Content $configFileName
}

function Test-Jar([string]$promptMessage) {
    $data = ''
    While (($null -eq $data) -or ($data -eq '')) {
        [string]$data = Read-Host -Prompt $promptMessage

        if (($null -eq $data) -or ($data -eq '')) {
            Write-Output ''
            $data = ''
            Invaild-Choice "You cannot enter a null/empty name!"
        }
        else {
            return $data + '.jar'
        }
    }
}

function Confirm-Custom-Jar-Location(){
    $answer = Read-Host -Prompt  "Would you like to add a custom path for your jar file? [Y]es/[N]o"
    if (($null -eq $answer) -or ($answer -eq '')) {
        Write-Output ''
        $answer = ''
        Invaild-Choice "You cannot enter a null/empty name!"
        Confirm-Custom-Jar-Location
    }
    else {
        switch ($answer.ToUpper()) {
            'Y' {
                 return $true
            }
            'N' {
                return $false
            }
            default {
                Invaild-Choice "INVALID CHOICE! PLEASE ENTER ONE OF THE CHOICES LISTED!"
                Confirm-Custom-Jar-Location
            }
        }
    }
}

function Test-Jar-Path([string]$promptMessage, [string]$jarFile) {
    $data = ''
    While (($null -eq $data) -or ($data -eq '')) {
        $data = Read-Host -Prompt $promptMessage
        $dataWithJar = -Join ($currentLocation,"\",$data,"\",$jarFile)

        if (($null -eq $data) -or ($data -eq '')) {
            Write-Output ''
            $data = ''
            Invaild-Choice "You cannot enter a null/empty name!"
        }
        elseif (!(Test-Path $dataWithJar)) {
            Write-Output ''
            Invaild-Choice "Could not locate $jarFile in the folder, $data"
            $data = ''
        }
        else {
            return -Join ($currentLocation, "\", $data,"\")
        }
    }
}
function Test-Use-Custom-Location(){
    if($Script:INFO.Use_Custom_Location -eq $true){
        Set-Location $Script:INFO.Custom_Location
    }else{
        Set-Location $currentLocation
    }
}

function Test-Version([string]$promptMessage) {
    $data = ''
    While ($data -eq '') {
        $data = Read-Host -Prompt $promptMessage
        $minVer = [version]'1.0.0'
        $maxVer = [version]'999.999.999'

        # not matching NOT 0-9 & '.' [ie - only 0-9 & '.']
        # must contain at least one '.'
        # must START with a digit
        # must END with a digit
        if (($data -notmatch '[^0-9.]') -and ($data -match '\.') -and ($data[0] -match '[0-9]') -and ($data[-1] -match '[0-9]') -and ($data -ge $minVer) -and ($data -le $maxVer)) {
            return $data
        }
        else {
            $data = ''
            Invaild-Choice "The value [$data] MUST be a version (major, minor, build) ranging between $minVer to $maxVer!"
        }
    }
}

function Test-Integer([string]$promptMessage) {
    $data = ''
    While (($null -eq $data) -or ($data -eq '') -or ($data -eq '0') -or (-not ($data -notmatch '[^\d]'))) {

        [int]$data = Read-Host -Prompt $promptMessage
        if (($null -eq $data) -or ($data -eq '') -or ($data -eq '0')) {
            Write-Host ''
            $data = ''
            Invaild-Choice "The value [$data] cannot be null, empty or 0!"
        }
        elseif (-not ($data -notmatch '[^\d]')) {
            Write-Output ''
            $data = ''
            Invaild-Choice "The value [$data] MUST be an integer!"
        }
        else {
            return $data
        }

    }
}

function Test-RAM-Type() {
    $ramType = ''
    $ValidChoices = ('M', 'G')
    While ($ramType -notin $ValidChoices) {
        $ramType = (Read-Host -Prompt 'Would you like to use [M]egabytes or [G]igabytes?').ToUpper()

        if ($ramType -notin $ValidChoices) {
            $ramType = ''
            Invaild-Choice "INVALID CHOICE! PLEASE ENTER ONE OF THE CHOICES LISTED!"
        }
        else {
            return $ramType
        }
    }
}

#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# BEGIN FUNCTION CALLS #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#

Do {

    Clear-Host
    If (!(Test-Path $configFileName)) {
        Set-Up-Console
    }
    else {
        Invoke-Main-Menu
    }

} Until ($QuitConsole = $true)