Skip to content

Instantly share code, notes, and snippets.

@EdGruberman
Created January 8, 2013 02:28
Show Gist options
  • Save EdGruberman/4480548 to your computer and use it in GitHub Desktop.
Save EdGruberman/4480548 to your computer and use it in GitHub Desktop.
Minecraft Server Wrapper
<#
powershell.exe -noexit ". 'D:\Documents\Personal\Games\Minecraft\Server\MCS.ps1'"
#>
Add-Type -AssemblyName 'System.Messaging'
Add-Type -AssemblyName 'System.Web'
Add-Type -AssemblyName 'System.Web.Extensions'
Function Initialize
{
$Global:datLastStarted = Get-Date
$Global:Players = @{}
$Global:TaskQueue = New-Object Collections.Queue
$Global:TimerStarts = @{}
#--Setup automatic world saving
If ((GetConfiguration('AutoSave')) -ne [DBNull]::Value) {
#--Start based on last start, but not longer than normal
$Initial = (GetConfiguration('AutoSave')) * 60 * 1000
$Last = (New-TimeSpan (GetStatus('LastSaveRequest')) $Global:datLastStarted.ToUniversalTime()).TotalMilliseconds
If ($Last -lt $Initial) { $Initial = $Initial - $Last } Else { $Initial = 5 * 60 * 1000 }
$Global:timAutoSave = New-Object System.Timers.Timer
$Global:timAutoSave.Interval = $Initial
$Global:timAutoSave.Enabled = $True
Register-ObjectEvent $timAutoSave 'Elapsed' -SourceIdentifier 'AutoSave' -Action { timAutoSave_Elapsed @Args } | Out-Null
$Global:timAutoSave.Start()
$Global:TimerStarts.Save = Get-Date
}
#--Setup automatic backup
If ((GetConfiguration('AutoBackup')) -ne [DBNull]::Value) {
#--Start based on last start, but not longer than normal
$Initial = (GetConfiguration('AutoBackup')) * 60 * 1000
$Last = (New-TimeSpan (GetStatus('LastBackupRequest')) $Global:datLastStarted.ToUniversalTime()).TotalMilliseconds
If ($Last -lt $Initial) { $Initial = $Initial - $Last } Else { $Initial = 5 * 60 * 1000 }
$Global:timAutoBackup = New-Object System.Timers.Timer
$Global:timAutoBackup.Interval = $Initial
$Global:timAutoBackup.Enabled = $True
Register-ObjectEvent $timAutoBackup 'Elapsed' -SourceIdentifier 'AutoBackup' -Action { timAutoBackup_Elapsed @Args } | Out-Null
$Global:timAutoBackup.Start()
$Global:TimerStarts.Backup = Get-Date
}
#--Setup automatic image creation
If ((GetConfiguration('AutoImages')) -ne [DBNull]::Value) {
#--Start based on last start, but not longer than normal
$Initial = (GetConfiguration('AutoImages')) * 60 * 1000
$Last = (New-TimeSpan (GetStatus('LastImagesRequest')) $Global:datLastStarted.ToUniversalTime()).TotalMilliseconds
If ($Last -lt $Initial) { $Initial = $Initial - $Last } Else { $Initial = 5 * 60 * 1000 }
$Global:timAutoImages = New-Object System.Timers.Timer
$Global:timAutoImages.Interval = $Initial
$Global:timAutoImages.Enabled = $True
Register-ObjectEvent $timAutoImages 'Elapsed' -SourceIdentifier 'AutoImages' -Action { timAutoImages_Elapsed @Args } | Out-Null
$Global:timAutoImages.Start()
$Global:TimerStarts.Images = Get-Date
}
#--Setup automatic backup pruning
If ((GetConfiguration('AutoPrune')) -ne [DBNull]::Value) {
#--Start based on last start, but not longer than normal
$Initial = (GetConfiguration('AutoPrune')) * 60 * 1000
If (GetStatus('LastPruneRequest'))
{ $Last = (New-TimeSpan (GetStatus('LastPruneRequest')) $Global:datLastStarted.ToUniversalTime()).TotalMilliseconds }
If ($Last -lt $Initial) { $Initial = $Initial - $Last }
$Global:timAutoPrune = New-Object System.Timers.Timer
$Global:timAutoPrune.Interval = $Initial
$Global:timAutoPrune.Enabled = $True
Register-ObjectEvent $timAutoPrune 'Elapsed' -SourceIdentifier 'AutoPrune' -Action { timAutoPrune_Elapsed @Args } | Out-Null
$Global:timAutoPrune.Start()
$Global:TimerStarts.Prune = Get-Date
}
#--Setup live player data monitor
$LivePlayerData = GetConfiguration 'LivePlayerData'
If ($LivePlayerData -ne [DBNull]::Value) {
$FSW = New-Object System.IO.FileSystemWatcher (Split-Path -Parent $LivePlayerData), (Split-Path -Leaf $LivePlayerData)
$FSW.NotifyFilter = [System.IO.NotifyFilters]::LastWrite
Get-EventSubscriber | Where-Object { $_.SourceIdentifier -eq 'LivePlayerData_Changed' } | Unregister-Event
Get-Job | Where-Object { $_.Name -eq 'LivePlayerData_Changed' } | Remove-Job
Register-ObjectEvent $FSW 'Changed' -SourceIdentifier 'LivePlayerData_Changed' -Action { LivePlayerData_Changed @Args } | Out-Null
}
$Global:blnMCSPrepared = $True
#Twitter_Initialize
}
Function Deinitialize
{
#Get-EventSubscriber | Where-Object { $_.SourceIdentifier -eq 'LivePlayerData_Changed' } | Unregister-Event
#Get-Job | Where-Object { $_.Name -eq 'LivePlayerData_Changed' } | Remove-Job
Unregister-Event 'AutoSave' -ErrorAction:SilentlyContinue; Remove-Job 'AutoSave' -ErrorAction:SilentlyContinue
Unregister-Event 'AutoBackup' -ErrorAction:SilentlyContinue; Remove-Job 'AutoBackup' -ErrorAction:SilentlyContinue
Unregister-Event 'AutoImages' -ErrorAction:SilentlyContinue; Remove-Job 'AutoImages' -ErrorAction:SilentlyContinue
Unregister-Event 'AutoPrune' -ErrorAction:SilentlyContinue; Remove-Job 'AutoPrune' -ErrorAction:SilentlyContinue
If ($Global:TaskQueue) { If ($Global:TaskQueue.GetType().Name -eq 'Queue') { $Global:TaskQueue.Clear() } }
$Global:TaskInProgress = $False
#Twitter_Deinitialize
}
Function LivePlayerData_Changed ([System.IO.FileSystemWatcher]$Sender, [System.IO.FileSystemEventArgs]$e) {
$Last = (Get-ChildItem $e.FullPath).LastWriteTimeUtc
If ($Last -ne $Global:LastLivePlayerData ) {
$Global:LastLivePlayerData = $Last
ProcessLivePlayerData (Get-Content $e.FullPath)
}
Trap
{
Write-Host "Error in LivePlayerData_Changed" -ForegroundColor Red
Write-Host $_ -ForegroundColor Red
Write-Host "Ln $($_.InvocationInfo.ScriptLineNumber) Col $($_.InvocationInfo.OffsetInLine): $($_.InvocationInfo.Line)" -ForegroundColor Red
Continue
}
}
Function ProcessLivePlayerData ([String]$JSON) {
$Serializer = New-Object System.Web.Script.Serialization.JavaScriptSerializer
$Markers = $Serializer.DeserializeObject($JSON)
If ($Markers -eq $Null) { Return }
ForEach ($Player In $Markers) {
#--Update player coordinates in database
$Command = New-Object System.Data.SqlClient.SqlCommand("UpdatePlayerLocation", $SQL)
$Command.CommandType = [System.Data.CommandType]::StoredProcedure
$Command.Parameters.Add('@PlayerName', [System.Data.SqlDbType].NVarChar).Value = $Player.msg
$Command.Parameters.Add('@Updated' , [System.Data.SqlDbType].String).Value = (Get-Date $Player.timestamp).ToUniversalTime()
$Command.Parameters.Add('@World' , [System.Data.SqlDbType].NVarChar).Value = $Player.world
$Command.Parameters.Add('@X' , [System.Data.SqlDbType].Float).Value = $Player.x
$Command.Parameters.Add('@Y' , [System.Data.SqlDbType].Float).Value = $Player.y
$Command.Parameters.Add('@Z' , [System.Data.SqlDbType].Float).Value = $Player.z
If ($SQL.State -eq 'Closed') { $SQL.Open() }
[Void]$Command.ExecuteNonQuery()
$SQL.Close()
}
}
Function GetConfiguration ([String]$Parameter)
{
$Command = New-Object System.Data.SqlClient.SqlCommand("SELECT [$Parameter] FROM Configuration WHERE Name = '$Global:Configuration'", $SQL)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$Command.ExecuteScalar()
$SQL.Close()
}
Function GetStatus ([String]$Field)
{
$Command = New-Object System.Data.SqlClient.SqlCommand("SELECT [$Field] FROM Status", $SQL)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$Value = $Command.ExecuteScalar()
$SQL.Close()
If ($Value -ne [DBNull]::Value) { $Value = [DateTime]$Value } Else { $Value = $Null }
Return $Value
}
Function GetPlayer ([String]$Player)
{
$Command = New-Object System.Data.SqlClient.SqlCommand("SELECT * FROM Players WHERE Name = '$Player'", $SQL)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$Command.ExecuteReader()
$SQL.Close()
}
Function GetMotD
{
$Command = New-Object System.Data.SqlClient.SqlCommand("SELECT * FROM LastMotD", $SQL)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$Command.ExecuteReader()
$SQL.Close()
}
Function FormatMotD
{
$MotD = GetMotD
$Updated = (Duration $MotD['Updated'].ToLocalTime()).Split(' ')[0,1]
Return "Message of the Day ($Updated ago by $($MotD['UpdatedBy'])): $($MotD['Text'])"
}
Function SetStatus ([String]$Field)
{
$Command = New-Object System.Data.SqlClient.SqlCommand("UPDATE Status SET [$Field] = GETUTCDATE()", $SQL)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
[Void]$Command.ExecuteNonQuery()
$SQL.Close()
}
Function SetPlayer ([String]$Name, [System.Data.Common.DbParameter]$Parameter, [Boolean]$FixCase = $False)
{
#Add player if they don't already exist in database
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$Players_Name = (New-Object System.Data.SqlClient.SqlCommand("SELECT Name FROM Players WHERE Name = '$Name'", $SQL)).ExecuteScalar()
If ($Players_Name -eq $Null)
{
$Command = New-Object System.Data.SqlClient.SqlCommand("INSERT INTO Players (Name) VALUES ('$Name')", $SQL)
[Void]$Command.ExecuteNonQuery()
}
ElseIf ( $FixCase -and ($Players_Name -cne $Name) )
{
$Command = New-Object System.Data.SqlClient.SqlCommand("UPDATE Players SET Name = '$Name' WHERE Name = '$Name'", $SQL)
[Void]$Command.ExecuteNonQuery()
}
$SQL.Close()
If (!$Parameter) { Return }
$Command = New-Object System.Data.SqlClient.SqlCommand("UPDATE Players SET [$($Parameter.ParameterName)] = @Value WHERE Name = '$Name'", $SQL)
$Value = New-Object System.Data.SqlClient.SqlParameter('@Value', $Parameter.DbType)
$Value.Direction = [System.Data.ParameterDirection]::Input
$Value.Value = $Parameter.Value
[Void]$Command.Parameters.Add($Value)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
[Void]$Command.ExecuteNonQuery()
$SQL.Close()
}
Function SetMotD ([String]$DirtyText, [DateTime]$Updated, [String]$UpdatedBy)
{
$Command = New-Object System.Data.SqlClient.SqlCommand("INSERT INTO MotD (Text, Updated, UpdatedBy) SELECT @Text, '$Updated', P.ID FROM Players AS P WHERE P.Name = '$UpdatedBy'", $SQL)
$Text = New-Object System.Data.SqlClient.SqlParameter('@Text', [System.Data.DbType]::String)
$Text.Direction = [System.Data.ParameterDirection]::Input
$Text.Value = $DirtyText
[Void]$Command.Parameters.Add($Text)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
[Void]$Command.ExecuteNonQuery()
$SQL.Close()
}
Function Global:MCS.Start
{
If (!(SDP.HasExited)) { Write-Host 'Server already started.'; Return }
#-- Define process configuration
$psiServer = New-Object System.Diagnostics.ProcessStartInfo
$psiServer.UseShellExecute = $False
$psiServer.RedirectStandardOutput = $True
$psiServer.RedirectStandardError = $True
$psiServer.RedirectStandardInput = $True
$psiServer.FileName = GetConfiguration 'Java'
$psiServer.Arguments = (GetConfiguration 'JavaArguments') + ' -jar "' + (GetConfiguration 'MinecraftJAR') + '" ' + (GetConfiguration 'MinecraftArguments')
$psiServer.WorkingDirectory = $strScriptPath
SDP.Start $psiServer
}
Function Global:MCS.Stop
{
If (SDP.HasExited) { Write-Host 'Server not started.'; Return }
If ($Global:blnMCSPrepared -ne $True) { Write-Host 'Server not prepared to take commands yet.'; Return }
MCS 'save-all'
MCS 'stop'
}
Function Global:MCS ([String]$strCommand)
{
If (SDP.HasExited) { Write-Host 'Server not started.'; Return }
If ($Global:blnMCSPrepared -ne $True) { Write-Host 'Server not prepared to take commands yet.'; Return }
SDP.WriteLine $strCommand
#SDP.WriteLine "#$strCommand"
}
Function SDP.HasExited
{
Return ( ([String]::IsNullOrEmpty($Global:prcProcess.HasExited)) -Or ($Global:prcProcess.HasExited) )
}
Function SDP.Start ([System.Diagnostics.ProcessStartInfo]$psiStartInfo)
{
$Global:prcProcess = New-Object System.Diagnostics.Process
$Global:prcProcess.EnableRaisingEvents = $True
$Global:prcProcess.StartInfo = $psiStartInfo
Get-EventSubscriber | Where-Object { $_.SourceIdentifier -eq 'Process.OutputData' } | Unregister-Event
Get-EventSubscriber | Where-Object { $_.SourceIdentifier -eq 'Process.ErrorData' } | Unregister-Event
Get-EventSubscriber | Where-Object { $_.SourceIdentifier -eq 'Process.Exited' } | Unregister-Event
Register-ObjectEvent $Global:prcProcess 'OutputDataReceived' -SourceIdentifier 'Process.OutputData' -Action { prcProcess_OutputDataReceived @Args } | Out-Null
Register-ObjectEvent $Global:prcProcess 'ErrorDataReceived' -SourceIdentifier 'Process.ErrorData' -Action { prcProcess_ErrorDataReceived @Args } | Out-Null
Register-ObjectEvent $Global:prcProcess 'Exited' -SourceIdentifier 'Process.Exited' -Action { prcProcess_Exited @Args } | Out-Null
$Global:prcProcess.Start() | Out-Null
$Global:prcProcess.BeginOutputReadLine()
$Global:prcProcess.BeginErrorReadLine()
}
Function SDP.WriteLine ([String]$strText)
{
$Global:prcProcess.StandardInput.WriteLine($strText)
Trap
{
Write-Host "Error in SDP.WriteLine" -ForegroundColor Red
Write-Host $_ -ForegroundColor Red
Write-Host "Ln $($_.InvocationInfo.ScriptLineNumber) Col $($_.InvocationInfo.OffsetInLine): $($_.InvocationInfo.Line)" -ForegroundColor Red
Continue
}
}
Function prcProcess_ErrorDataReceived ([System.Object]$sender, $e)
{
If ([String]::IsNullOrEmpty($e.Data)) { Return }
Write-Host $e.Data
If ($e.Data.IndexOf(']') -gt 21)
{
If (!$Global:Log) { $Global:Log = New-Object System.Collections.Queue }
$Global:Log.Enqueue($e.Data)
If ($Global:timProcessLog.Enabled -ne $True)
{
If (!($Global:timProcessLog))
{
$Global:timProcessLog = New-Object System.Timers.Timer
$Global:timProcessLog.Interval = 100
$Global:timProcessLog.AutoReset = $False
}
Register-ObjectEvent $Global:timProcessLog 'Elapsed' -SourceIdentifier 'ProcessLog' -Action { timProcessLog_Elapsed @Args } | Out-Null
$Global:timProcessLog.Start()
}
}
Trap
{
Write-Host "Error Processing Standard Error Stream" -ForegroundColor Red
Write-Host $_ -ForegroundColor Red
Write-Host "Ln $($_.InvocationInfo.ScriptLineNumber) Col $($_.InvocationInfo.OffsetInLine): $($_.InvocationInfo.Line)" -ForegroundColor Red
#Write-Error 'Error Processing Standard Error Stream Test' -ErrorID STDERR1 -TargetObject $_
Continue
}
}
Function prcProcess_OutputDataReceived ([System.Object]$sender, $e)
{
If ([String]::IsNullOrEmpty($e.Data)) { Return }
Write-Host $e.Data
Trap
{
Write-Host "Error Processing Standard Output Stream" -ForegroundColor Red
Write-Host $_ -ForegroundColor Red
Write-Host "Ln $($_.InvocationInfo.ScriptLineNumber) Col $($_.InvocationInfo.OffsetInLine): $($_.InvocationInfo.Line)" -ForegroundColor Red
Continue
}
}
Function prcProcess_Exited ([System.Object]$sender, $e)
{
$Global:prcProcess.CancelOutputRead()
$Global:prcProcess.CancelErrorRead()
Unregister-Event 'Process.OutputData'
Unregister-Event 'Process.ErrorData'
Unregister-Event 'Process.Exited'
Remove-Job 'Process.OutputData'
Remove-Job 'Process.ErrorData'
Remove-Job 'Process.Exited'
Write-Host """$(($sender -As [System.Diagnostics.Process]).StartInfo.FileName)"" has exited."
If ($Global:blnRestart -eq $True) { MCS.Start; $Global:blnRestart = $False }
}
Function timProcessLog_Elapsed([System.Object]$sender, [System.Timers.ElapsedEventArgs]$e)
{
If ($Global:Log.Count -eq 0)
{
If ($Global:timProcessLog.Enabled -eq $True) { $Global:timProcessLog.Stop() }
Get-EventSubScriber | Where-Object { $_.SourceIdentifier -eq 'ProcessLog' } | Unregister-Event
Remove-Job -Name 'ProcessLog'
Return
}
ProcessLog
$Global:timProcessLog.Start()
Trap
{
Write-Host "Error Processing Log" -ForegroundColor Red
Write-Host $_ -ForegroundColor Red
Write-Host "Ln $($_.InvocationInfo.ScriptLineNumber) Col $($_.InvocationInfo.OffsetInLine): $($_.InvocationInfo.Line)" -ForegroundColor Red
Continue
}
}
Function ProcessLog
{
$strLine = $Global:Log.Dequeue()
$strLine = StripColorCodes($strLine)
$datOccured = $strLine.Substring(0, 19)
$strCategory = $strLine.Substring(21, $strLine.IndexOf(']') - 21)
$strEntry = $strLine.Substring($strLine.IndexOf(']') + 2)
ParseEntry $datOccured $strCategory $strEntry
Trap
{
Write-Host "Error in ProcessLog" -ForegroundColor Red
Write-Host $_ -ForegroundColor Red
Write-Host "Ln $($_.InvocationInfo.ScriptLineNumber) Col $($_.InvocationInfo.OffsetInLine): $($_.InvocationInfo.Line)" -ForegroundColor Red
Continue
}
}
Function StripColorCodes ([String]$strLine)
{
[RegEx]::Replace($strLine, 'º.', '')
}
Function ParseEntry ([DateTime]$datOccured, [String]$Category, [String]$strEntry)
{
If ($Category -ne 'INFO') { Return }
#--Game Chat
#Example: <EdGruberman> Hello World1!
If ($strEntry.StartsWith('<'))
{
$Player = $strEntry.Split(('<', '>'))[1]
$Text = $strEntry.Substring($strEntry.IndexOf('>') + 2)
If ($Global:Players.$Player.AFK -eq $True)
{
If (@($Mail.$Player.Message | Where-Object { $_.Deleted -eq $False -And $_.Read -eq $False }).Count -gt 0) { CheckMail $Player $True }
}
$Global:Players.$Player.AFK = $False
If ($Text.StartsWith('=')) { ProcessCommand $datOccured $Player $Text.Substring(1) }
Else
{
If (($Text.Replace("* $Player ", '').Split(" ").Length - 1) -le 2) { Return }
SetPlayer $Player (New-Object System.Data.SqlClient.SqlParameter('RandomComment', $Text))
}
}
#--Action Chat
#Example: * EdGruberman hides
ElseIf ($strEntry.StartsWith('*'))
{
$Player = $strEntry.Split(' ')[1]
If ($Global:Players.$Player.AFK -eq $True)
{
If (@($Mail.$Player.Message | Where-Object { $_.Deleted -eq $False -And $_.Read -eq $False }).Count -gt 0) { CheckMail $Player $True }
}
$Global:Players.$Player.AFK = $False
If (($strEntry.Replace("* $Player ", '').Split(" ").Length - 1) -le 2) { Return }
SetPlayer $Player (New-Object System.Data.SqlClient.SqlParameter('RandomComment', $strEntry))
}
#--Private Command
#Example: EdGruberman issued server command: command parameter1 parameter2
#Example: the_Huntress tried command: command something
ElseIf ($strEntry.Split(':')[0].EndsWith('command'))
{
$Player = $strEntry.Split(' ')[0]
$Command = $strEntry.Split(':')[1].Split(' ', 2)[1]
ProcessCommand $datOccured $Player $Command $True
}
#--Private Command (hMod format)
#Example: Command used by EdGruberman /command parameter1 parameter2
ElseIf ($strEntry.StartsWith('Command used by '))
{
$Player = $strEntry.Split(' ')[3]
$Command = $strEntry.Split('/')[1]
ProcessCommand $datOccured $Player $Command $True
}
#Example: Starting minecraft server version 0.2.2
ElseIf ($strEntry.StartsWith('Starting minecraft server version '))
{
$Global:Version = $strEntry.Split(' ')[-1]
}
#--Minecraft server prepared
#Example: Done! For help, type "help" or "?"
ElseIf ($strEntry -like 'Done (*ns)! For help, type "help" or "?"')
{
Initialize
}
#--Minecraft server stopped
#Example: Stopping server
ElseIf ($strEntry -eq 'Stopping server')
{
$Global:blnMCSPrepared = $False
$strNow = Get-Date -Date (Get-Date).ToUniversalTime() -Format 'yyyyMMddHHmmss\Z'
Copy-Item "$strScriptPath\server.log" "$(GetConfiguration('Logs'))\$strNow.log"
Deinitialize
}
#Example CONSOLE: Forcing save..
ElseIf ($strEntry.EndsWith(': Forcing save..'))
{
$Global:blnSaveInProgress = $True
}
#Example CONSOLE: Save complete.
ElseIf ($strEntry.EndsWith(': Save complete.'))
{
SetStatus 'LastSave'
$Global:blnSaveInProgress = $False
MCS 'say Save completed.'
}
#Example CONSOLE: Disabling level saving..
ElseIf ($strEntry.EndsWith(': Disabling level saving..'))
{
If ($Global:TaskInProgress -eq $True) { ProcessTask '' $True }
}
#--Player Connection
#Example: EdGruberman [/127.0.0.1:54160] logged in with entity id 5
ElseIf ($strEntry.Contains(' logged in with entity id '))
{
$Name = $strEntry.Split(' ')[0]
$Address = $strEntry.Split(('[', ']'))[1]
If ($Global:Players.ContainsKey($Name)) { $Global:Players.Remove($Name) }
$Global:Players.Add($Name, @{ Address = $Address; AFK = $False })
SetPlayer $Name $Null $True
$Player = GetPlayer($Name)
If ($Player['FirstConnection'] -eq [DBNull]::Value) { SetPlayer $Name (New-Object System.Data.SqlClient.SqlParameter('FirstConnection', ($datOccured).ToUniversalTime())) }
If ($Player['Connections'] -eq [DBNull]::Value) { $Connections = 1 } Else { $Connections = $Player['Connections'] + 1 }
SetPlayer $Name (New-Object System.Data.SqlClient.SqlParameter('Connections', [String]$Connections))
If (!(MemberOf 'Players' $Name))
{
SetPlayer $Name (New-Object System.Data.SqlClient.SqlParameter('LastConnection', ($datOccured).ToUniversalTime()))
MCS "say Whitelist Violation; $Name is not in Players group."
MCS "kick $Name"
Return
}
$MotD = GetMotD
If ($MotD -ne $Null)
{
If ($Player['LastConnection'] -eq [DBNull]::Value) { Respond (FormatMotD) $Name $True }
Else {
$LastTold = New-TimeSpan $Player['LastConnection'] ($datOccured).ToUniversalTime()
If ( ($LastTold.TotalMinutes -gt 60) -or ($MoTD['Updated'] -gt $Player['LastConnection']) ) { Respond (FormatMotD) $Name $True }
}
}
SetPlayer $Name (New-Object System.Data.SqlClient.SqlParameter('LastConnection', $datOccured.ToUniversalTime()))
If (@($Mail.$Name.Message | Where-Object { $_.Deleted -eq $False -And $_.Read -eq $False }).Count -gt 0) { CheckMail $Name $True }
}
#--Player Disconnection
#Example: EdGruberman lost connection: Quitting
ElseIf ($strEntry.Split(':')[0].EndsWith(' lost connection'))
{
$Name = $strEntry.Split(' ')[0]
$Global:Players.Remove($Name)
If (!($strEntry.EndsWith('disconnect.quitting'))) { MCS "say $Name lost connection;$($strEntry.Split(':')[-1])" }
SetPlayer $Name (New-Object System.Data.SqlClient.SqlParameter('LastDisconnection', $datOccured.ToUniversalTime()))
}
#--Player Kicked by Console (No disconnection log entry after)
#Example: CONSOLE: Kicking EdGruberman
ElseIf ($strEntry.StartsWith('CONSOLE: Kicking '))
{
$Name = $strEntry.Split(' ')[2]
$Global:Players.Remove($Name)
SetPlayer $Name (New-Object System.Data.SqlClient.SqlParameter('LastDisconnection', $datOccured.ToUniversalTime()))
}
#--Dropped Connection
#Example: Disconnecting /24.17.220.9:1924: Took too long to log in
ElseIf ($strEntry.StartsWith('Disconnecting '))
{
$Address = $strEntry.Split((' ', ': '), [System.StringSplitOptions]"None")[1]
ForEach ($i In $Global:Players.Keys) { If ($Global:Players.$i.Address -eq $Address) { $Name = $i } }
If ( $Name )
{
$Global:Players.Remove($Name)
SetPlayer $Name (New-Object System.Data.SqlClient.SqlParameter('LastDisconnection', $datOccured.ToUniversalTime()))
}
}
}
Function ProcessCommand ([DateTime]$datOccured, [String]$strRequestor, [String]$strText, [Boolean]$Private = $False)
{
$Command = $strText.Split(' ')[0].ToLower()
$strParameters = $strText.Split(' ', 2)[1]
If ($Command -eq 'players') { $Command = 'who' }
#If ($Command -eq 'list') { $Command = 'who' }
Switch ($Command)
{
#--Everyone
'who'
{
If (!($strParameters))
{
$strOutput = ''
ForEach ($i In ($Global:Players.Keys | Sort-Object))
{
If (![String]::IsNullOrEmpty($strOutput)) { $strOutput += ', ' }
$strOutput += $i
If ($Global:Players.$i.AFK -eq $True) { $strOutput += '(AFK)' }
}
If ($Global:Players.Count -ne 1) { $strPlural = 's' }
Respond "Who is connected = $strOutput `($($Global:Players.Count) player$strPlural)" $strRequestor $Private
Return
}
#Who <Player>[ groups]
#If (!(MemberOf 'Moderators' $strRequestor)) { Return }
$Name = $strParameters.Split(' ')[0]
$Detail = $strParameters.Split(' ')[1]
$Player = GetPlayer($Name)
If ($Detail -match '^g[r]?[o]?[u]?[p]?[s]?$')
{
Respond "-- $($Player["Name"]) is a member of:" $strRequestor $Private
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$Groups = (New-Object System.Data.SqlClient.SqlCommand("SELECT * FROM Members WHERE Players_Name = '$Name' ORDER BY Groups_Name", $SQL)).ExecuteReader()
While ( $Groups.Read() )
{
$strAdded = (Duration ($Groups['Added']).ToLocalTime()).Split(' ')[0]
Respond "$($Groups['Groups_Name']) group `($strAdded ago by $($Groups['AddedBy']): `"$($Groups['Comments'])`"`)" $strRequestor $Private
}
$Groups.Close()
$SQL.Close()
}
Else
{
If (($Player -ne $Null) -and ($Player['LastConnection'] -ne [DBNull]::Value)) { $strLastConnected = "last connected $((Duration $Player['LastConnection'].ToLocalTime()).Split(' ')[0]) ago" }
Else { $strLastConnected = 'has not connected yet' }
If ($Player -eq $Null) { $PlayerName = $Name } Else { $PlayerName = $Player["Name"] }
Respond "-- $PlayerName $strLastConnected" $strRequestor $Private
If (($Player -ne $Null) -and ($Player['FirstConnection'] -ne [DBNull]::Value)) { Respond "$($Player['Connections']) Connections `(First $((Duration $Player['FirstConnection'].ToLocalTime()).Split(' ')[0]) ago`)" $strRequestor $Private }
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$Groups = (New-Object System.Data.SqlClient.SqlCommand("SELECT Groups_Name FROM Members WHERE Players_Name = '$Name' ORDER BY Groups_Name", $SQL)).ExecuteReader()
While ( $Groups.Read() )
{
If ($MemberOf -ne $Null) { $MemberOf += ', ' }
$MemberOf += $Groups['Groups_Name']
}
$Groups.Close()
$SQL.Close()
If ($MemberOf) { Respond "Member of $MemberOf" $strRequestor $Private }
If (($Player -ne $Null) -and ($Player['RandomComment'] -ne [DBNull]::Value)) { Respond "Random Comment: `"$($Player['RandomComment'])`"" $strRequestor $Private }
If ($Player -ne $Null) { Respond "`(For group detail: /Who $($Player["Name"]) Groups`)" $strRequestor $Private }
}
}
'afk'
{
$Global:Players.$strRequestor.AFK = $True
ProcessCommand $datOccured $strRequestor 'who' $Private
}
'status'
{
$strLastStarted = (Duration $Global:datLastStarted).Split(' ')[0,1]
If ((GetStatus('LastSave')) -ne [DBNull]::Value) { $strLastSave = "finished $((Duration (GetStatus('LastSave')).ToLocalTime()).Split(' ')[0]) ago" }
Else { $strLastSave = 'is unknown' }
$strNextSave = ([String]::Join(' ', (Duration ($Global:TimerStarts.Save).AddMilliseconds($timAutoSave.Interval)).Split(' ')[0..1])).Replace('-', '')
If ((GetStatus('LastBackup')) -ne [DBNull]::Value) { $strLastBackup = "finished $((Duration (GetStatus('LastBackup')).ToLocalTime()).Split(' ')[0]) ago" }
Else { $strLastBackup = 'is unknown' }
$strNextBackup = ([String]::Join(' ', (Duration ($Global:TimerStarts.Backup).AddMilliseconds($timAutoBackup.Interval)).Split(' ')[0..1])).Replace('-', '')
If ((GetConfiguration('AutoImages')) -gt 0) {
If ((GetStatus('LastImages')) -ne [DBNull]::Value) { $strLastImages = "finished $((Duration (GetStatus('LastImages')).ToLocalTime()).Split(' ')[0]) ago" }
Else { $strLastImages = 'is unknown' }
$strNextImages = ([String]::Join(' ', (Duration ($Global:TimerStarts.Images).AddMilliseconds($timAutoImages.Interval)).Split(' ')[0..1])).Replace('-', '')
}
Respond "Version $Global:Version Started $strLastStarted ago" $strRequestor $Private
If ((GetConfiguration('AutoSave')) -gt 0) { Respond "Forced Save $strLastSave `(Next in $strNextSave`)" $strRequestor $Private }
If ((GetConfiguration('AutoBackup')) -gt 0) { Respond "Backup $strLastBackup `(Next in $strNextBackup`)" $strRequestor $Private }
If ((GetConfiguration('AutoImages')) -gt 0) { Respond "Image Update $strLastImages `(Next in $strNextImages`)" $strRequestor $Private }
}
'ping'
{
$Ping = New-Object System.Net.NetworkInformation.Ping
$Reply = $Ping.Send($Global:Players.$strRequestor.Address.Split(('/', ':'))[1])
If ($Reply.Status -ne 'TimedOut') { $Result = "is $($Reply.RoundTripTime)ms `($($Reply.Status)`)" } Else { $Result = 'timed out (Check your firewall)' }
Respond "Ping to $strRequestor $Result" $strRequestor $Private
}
#Mail[ <id>][ d[elete]]
'mail'
{
#No parameters - Read first unread mail
If (!($strParameters))
{
If (@($Mail.$strRequestor.Message | Where-Object { $_.Deleted -eq $False -And $_.Read -eq $False }).Count -gt 0)
{ ReadMail $strRequestor -1 $Private }
#If (@($Mail.$strRequestor.Message | Where-Object { $_.Deleted -eq $False -And $_.Read -eq $False }).Count -gt 0)
CheckMail $strRequestor $Private
Return
}
#Parameter supplied - Read/Delete associated mail
$ID = $strParameters.Split(' ')[0]
If ($strParameters.Split(' ')[1] -match '^d[e]?[l]?[e]?[t]?[e]?$')
{
DeleteMail $strRequestor $ID $Private
Return
}
ReadMail $strRequestor $ID $Private
}
#SendMail <To> <Message>
'sendmail'
{
If (!($strParameters)) { $strParameters = '' }
If ($strParameters.Split(' ', 2).Count -ne 2) { Respond 'Error: sendmail <To> <Msg> (e.g. =sendmail EdGruberman I have free obsidian for you!)' $strRequestor $Private; Return }
SendMail $strRequestor $strParameters.Split(' ')[0] $strParameters.Split(' ', 2)[1] $Private
}
#Inbox[ <page>]
'inbox'
{
If ($strParameters) { $Page = $strParameters.Split(' ')[0] }
If (!($Page) -Or !(IsNumeric($Page))) { $Page = 1 }
ReadMail $strRequestor 0 $Private $Page
}
#Time[ <Bias>]
'time'
{
If ($strParameters)
{
$strParameters = $strParameters.Split(' ')[0]
If (!(IsNumeric $strParameters.Split(':')[0])) { Respond "Invalid time bias. (e.g. =time -8)" $strRequestor $Private }
If ($strParameters.Split(':')[1])
{ If (!(IsNumeric $strParameters.Split(':')[1])) { Respond "Invalid time bias. (e.g. =time -8)" $strRequestor $Private } }
SetPlayer $strRequestor (New-Object System.Data.SqlClient.SqlParameter('ActiveTimeBias', $strParameters))
}
$Now = ToPlayerTime (Get-Date).ToUniversalTime() $strRequestor
Respond "Current Time: $(Get-Date -Date $($Now.PlayerTime) -Format 'h:mm:ss tt ddd d') `($($Now.Timezone)`)" $strRequestor $Private
}
'motd'
{
If (!$strParameters) { Respond "$(FormatMotD)" $strRequestor $Private; Return }
If (!(MemberOf 'Moderators' $strRequestor)) { Return }
SetMotD ($strParameters) $datOccured.ToUniversalTime() $strRequestor
Respond "MotD set successfully." $strRequestor $Private
}
#Kit[ <ID|Name>[ Use]]
'kit'
{
Kit $strParameters $strRequestor $Private
}
#Profile[ <key>[ <value>]]
'profile'
{
If ($strParameters)
{
$Key = $strParameters.Split(' ')[0]
If ($Key -ne 'Email') { Respond 'Invalid profile item. (e.g. =profile Email ed@rjump.com)' $strRequestor $Private; Return }
$Value = $strParameters.Split(' ', 2)[1]
If ($Value) { SetPlayer $strRequestor (New-Object System.Data.SqlClient.SqlParameter($Key, $Value)) }
$Player = GetPlayer($strRequestor)
Respond "$Key for $strRequestor is `"$($Player[$Key])`"" $strRequestor $Private
}
Else
{
$Key = 'Email'
$Player = GetPlayer($strRequestor)
Respond "-- Profile for $strRequestor" $strRequestor $Private
Respond "$($Key): $($Player[$Key])" $strRequestor $Private
Respond "`(To change: /Profile <Item> <Value>`)" $strRequestor $Private
}
}
#--Moderators
#White <MemberName> <Comments...>
'white'
{
If (!(MemberOf 'Moderators' $strRequestor)) { Return }
If (!($strParameters)) { Respond 'Usage: =White <Player> <Comments...>' $strRequestor $Private }
$Name = $strParameters.Split(' ')[0]
$Comments = $strParameters.Split(' ', 2)[1]
If (!$Comments) { Respond 'ERROR: Comments required. (e.g. =White EdGruberman He has no friends.)' $strRequestor $Private }
Else { Respond "$(ModifyMembers 'Add' $Name 'Players' $Comments $strRequestor)" $strRequestor $Private }
}
'size'
{
If (!(MemberOf 'Moderators' $strRequestor)) { Return }
$colItems = (Get-ChildItem (GetConfiguration('World')) -Recurse | Measure-Object -Property Length -Sum)
Respond ('say Current World Size = ' + "{0:N2}" -F ($colItems.Sum / 1MB) + " MB") $strRequestor $Private
}
'memory'
{
If (!(MemberOf 'Moderators' $strRequestor)) { Return }
$Global:prcProcess.Refresh()
$strMemory = "{0:N0}MB" -F ($Global:prcProcess.WorkingSet64 / 1MB)
Respond "Working Set Memory = $strMemory" $strRequestor $Private
}
'image'
{
If (!(MemberOf 'Moderators' $strRequestor)) { Return }
If ($strParameters) { $strParameters = $strParameters.Split(' ')[0] }
Else { $strParameters = '' }
If (!($Global:Images.ContainsKey($strParameters)))
{
Respond "Valid images: $($Global:Images.Keys | Sort-Object)" $strRequestor $Private
Return
}
ProcessTask @{ Command = 'Update Images'; Parameters = $strParameters; Requestor = $strRequestor; Private = $Private }
}
#--Administrators
'backup'
{
If (!(MemberOf 'Administrators' $strRequestor)) { Return }
ProcessTask @{ Command = 'Backup'; Requestor = $strRequestor; Private = $Private }
}
'save'
{
If (!(MemberOf 'Administrators' $strRequestor)) { Return }
ProcessTask @{ Command = 'Save'; Requestor = $strRequestor; Private = $Private }
}
'images'
{
If (!(MemberOf 'Administrators' $strRequestor)) { Return }
ProcessTask @{ Command = 'Update Images'; Requestor = $strRequestor; Private = $Private }
}
#Group <Action> <PlayerName> <GroupName> <Comments...>
'group'
{
If (!(MemberOf 'Administrators' $strRequestor)) { Return }
$Action = $strParameters.Split(' ')[0]
$PlayerName = $strParameters.Split(' ')[1]
$GroupName = $strParameters.Split(' ')[2]
$Comments = $strParameters.Split(' ', 4)[3]
Respond "$(ModifyMembers $Action $PlayerName $GroupName $Comments $strRequestor)" $strRequestor $Private
}
'restart'
{
If (!(MemberOf 'Administrators' $strRequestor)) { Return }
$Global:blnRestart = $True
MCS.Stop
}
}
}
Function Respond ([String]$Text, [String]$Name, [Boolean]$Private = $False)
{
If ($Private) { MCS "tell $Name $Text" }
Else { MCS "say $Text" }
}
Function Kit ([String]$Parameters, [String]$Requestor, [Boolean]$Private = $True)
{
#--Available Kits for Requestor
If (!$Parameters)
{
$Command = New-Object System.Data.SqlClient.SqlCommand("SELECT * FROM KitsAvailable WHERE Players_Name = '$strRequestor' ORDER BY Kits_ID", $SQL)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$KA = $Command.ExecuteReader()
While ( $KA.Read() )
{
$Text = "$($KA['Kits_Name'])"
If ($LastKits_Name -eq $KA['Kits_Name']) { $Text = $Text + " `(ID $($KA['ID'])`)" }
$Text = $Text + " | "
If ($KA['Factor'] -ne [DBNull]::Value) { $Text = $Text + "x$($KA['Factor']), " }
If ($KA['Total'] -ne [DBNull]::Value)
{
$UsesLeft = $KA['Total'] - $KA['Used']
$Text = $Text + "$UsesLeft left"
}
Else { $Text = $Text + 'Unlimited' }
If ($KA['Reload'] -ne [DBNull]::Value)
{
If ($KA['LastUsed'] -ne [DBNull]::Value)
{
If ( $KA['LastUsed'].AddSeconds($KA['Reload']) -gt (Get-Date).ToUniversalTime() )
{
$Reloaded = Duration (New-TimeSpan (Get-Date).ToUniversalTime() $KA['LastUsed'].AddSeconds($KA['Reload']))
$Text = $Text + ', reloads in ' + $Reloaded.Split(' ')[0,1]
}
}
Else { $Text = $Text + ', reloaded every ' + (Duration (New-TimeSpan -Seconds $KA['Reload'])) }
}
Respond $Text $Requestor $Private
$LastKits_Name = $KA['Kits_Name']
}
$KA.Close()
$SQL.Close()
If ($LastKits_Name -eq $Null) { Respond 'No kits currently available' $Requestor $Private }
Else { Respond '(For details: /Kit <KitName>)' $Requestor $Private }
Return
}
$Kit = $Parameters.Split(' ')[0]
If ($Parameters.Split(' ')[1] -eq 'use') { $Use = $True } Else { $Use = $False }
#--Retrieve Assignment Details
$Command = New-Object System.Data.SqlClient.SqlCommand
$Command.Connection = $SQL
If (IsNumeric($Kit))
{ $Command.CommandText = "SELECT * FROM KitsAvailable WHERE Players_Name = '$strRequestor' AND ID = $Kit ORDER BY ID" }
Else
{
$Command.CommandText = "SELECT * FROM KitsAvailable WHERE Players_Name = '$strRequestor' AND Kits_Name = @Kits_Name ORDER BY Kits_ID"
$Kits_Name = New-Object System.Data.SqlClient.SqlParameter('@Kits_Name', [System.Data.DbType]::String)
$Kits_Name.Direction = [System.Data.ParameterDirection]::Input
$Kits_Name.Value = $Kit
[Void]$Command.Parameters.Add($Kits_Name)
}
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$KA = $Command.ExecuteReader()
If (!$KA) { Respond 'Database Error' $strRequestor $Private; Return }
If (!$KA.Read()) { Respond 'Invalid Kit' $strRequestor $Private; Return }
If ( ($KA['Reload'] -ne [DBNull]::Value) -and ($KA['LastUsed'] -ne [DBNull]::Value) )
{ $Reloaded = New-TimeSpan (Get-Date).ToUniversalTime() $KA['LastUsed'].AddSeconds($KA['Reload']) }
If ($KA['Factor'] -ne [DBNull]::Value) { $Factor = $KA['Factor'] } Else { $Factor = 1 }
#--Determine Kit Contents
$Adapter = New-Object System.Data.SqlClient.SqlDataAdapter("SELECT * FROM KitContents WHERE Kits_ID = $($KA['Kits_ID']) ORDER BY Items_ID", $SQL)
$KC = New-Object System.Data.DataTable
$Adapter.Fill($KC)
$Contents = ''
ForEach ($Row In $KC.Rows)
{
If ($Contents -ne '') { $Contents = $Contents + ', ' }
$Contents = $Contents + $Row['Quantity'] * $Factor + ' ' + $Row['Items_Name']
}
If (!$Use)
{
#--Show Assignment Details
#Donator (ID 1) x10
$Text = "-- $($KA['Kits_Name']) `(ID $($KA['ID'])`)"
If ($Factor -ne 1 ) { $Text = $Text + " x$Factor" }
Respond $Text $Requestor $Private
#Uses = 1 left (2 total - 1 used)
$UsesLeft = $KA['Total'] - $KA['Used']
If ($KA['Total'] -ne [DBNull]::Value) { $Text = 'Uses = ' + $UsesLeft + ' left (' + $KA['Total'] + ' total - ' + $KA['Used'] + ' used)' }
Else { $Text = 'Uses = Unlimited' }
Respond $Text $Requestor $Private
#Immediate Reload | Reloaded every 1h 0s (Reloads in 37m 4s)
If ($KA['Reload'] -eq [DBNull]::Value) { $Text = 'Immediate Reload' }
Else
{
$Text = 'Reloaded every ' + (Duration (New-TimeSpan -Seconds $KA['Reload']))
If ( $Reloaded.TotalSeconds -gt 0 ) { $Text = $Text + ' (Reloads in ' + (Duration $Reloaded).Split(' ')[0,1] + ')' }
}
Respond $Text $Requestor $Private
$Contents = 'Contains ' + $Contents
}
Else
{
If ($Reloaded.TotalSeconds -gt 0) { Respond "Kit not reloaded `(Reloads in $((Duration $Reloaded).Split(' ')[0,1])`)" $Requestor $Private; Return }
#--Record usage
$Command = New-Object System.Data.SqlClient.SqlCommand("INSERT INTO KitUses (Players_ID, KitAssignments_ID, Used) SELECT P.ID, $($KA['ID']), GETUTCDATE() FROM Players AS P WHERE P.Name = '$Requestor'", $SQL)
$Affected = $Command.ExecuteNonQuery()
If ($Affected -ne 1) { Respond "Database Error" $Requestor $Private; Return }
#--Deliver Kit to Requestor
ForEach ($Row In $KC.Rows)
{
$Total = $Row['Quantity'] * $Factor
For ($i = 1; $i -le [Math]::Floor($Total / 64); $i++) { MCS "give $Requestor $($Row['Items_ID']) 64" }
If (($Total % 64) -gt 0) { MCS "give $Requestor $($Row['Items_ID']) $($Total % 64)" }
}
$Contents = 'Delivered ' + $Contents
}
#Contains 10 Sponge, 20 Cobblestone
Respond $Contents $Requestor $Private
#Special recognition for your support
Respond $KA['Kits_Comments'] $Requestor $Private
#EdGruberman - $10 donation on 1/4/2011. Thank you!
#Players group - Everyone is so cool you deserve this.
If ($KA['Groups_Name'] -ne [DBNull]::Value) { $Text = $KA['Groups_Name'] + ' group' }
Else { $Text = $KA['Players_Name'] }
$Text = $Text + ' - ' + $KA['KitAssignments_Comments']
Respond $Text $Requestor $Private
If (!$Use) { Respond '(To use: /Kit <KitName> Use)' $Requestor $Private }
$KA.Close()
$SQL.Close()
}
Function CheckMail([String]$Name, [Boolean]$Private = $False)
{
$NewMailCount = @($Mail.$Name.Message | Where-Object { $_.Deleted -eq $False -And $_.Read -eq $False }).Count
If ($NewMailCount -eq 0) { $Help = ' (To list: /Inbox)' } Else { $Help = ' (To read: /Mail)' }
Respond "$Name has $NewMailCount unread mail.$Help" $Name $Private
}
Function ReadMail ([String]$Player, [Int]$Index = 0, [Boolean]$Private = $False, [Int]$Page = 1)
{
$Messages = @($Mail.$Player.Message | Where-Object { $_.Deleted -eq $False } | Sort-Object 'Sent' -Descending)
If ($Messages.Count -eq 0) { Respond "$Player has 0 mail" $Player $Private }
If ($Index -ne 0)
{
If ($Index -eq -1)
{
$Messages = @($Mail.$Player.Message | Where-Object { $_.Deleted -eq $False -And $_.Read -eq $False } | Sort-Object 'Sent' -Descending)
$Index = 1
}
$Index = $Index - 1
If ($Index -gt $Messages.Count - 1) { Respond "Invalid mail request - $Player has $($Messages.Count) mail" $Player $Private; Return }
$Sent = ToPlayerTime $Messages[$Index].Sent $Player
If ($Messages[$Index].Read -eq $False)
{
$New = '*NEW* '
$Messages[$Index].Read = 'True'
$xmlMail.Save($XMLMAILFILE)
$Global:Mail = $Global:xmlMail.Mail
}
$Sent = (Get-Date $Sent.PlayerTime -Format 'h:mmtt ddd MMM dd') + " $($Sent.Timezone)"
Respond "[[ $($New)From: $($Messages[$Index].From) on $Sent" $Player $Private
Respond "$($Messages[$Index].Body) ]]" $Player $Private
Respond "(To respond: /SendMail $($Messages[$Index].From) <Message>)" $Player $Private
}
Else
{
If ($Page -lt 1 -Or $Page -gt ([int]($Messages.Count / 4 + .4)))
{ Respond "Invalid inbox request - $Player has $([int]($Messages.Count / 4 + .4)) pages of mail" $Player $Private; Return }
For ($i = (($Page - 1) * 4); ($i -lt $Messages.Count) -And ($i -lt ($Page * 4)); $i++)
{
If ($Messages[$i].Read -eq $False) { $New = '*NEW* ' } Else { $New = '' }
Respond "Mail #$($i + 1) - $($New)From $($Messages[$i].From) $((Duration $Messages[$i].Sent).Split(' ')[0]) ago" $Player $Private
}
Respond "Page $Page of $([int]($Messages.Count / 4 + .4)) `(For more: /Inbox <Page>`)" $Player $Private
}
}
Function DeleteMail ([String]$Player, [Int]$Index, [Boolean]$Private = $False)
{
$Messages = @($Mail.$Player.Message | Where-Object { $_.Deleted -eq $False } | Sort-Object 'Sent' -Descending)
If (!(IsNumeric($Index)) -Or ($Index -lt 1) -Or ($Index -gt $Messages.Count))
{ Respond "Invalid delete request - $Player only has $($Messages.Count) mail" $Player $Private; Return }
$Index = $Index - 1
$From = $Messages[$Index].From
$Sent = ToPlayerTime $Messages[$Index].Sent $Player
#$Messages[$Index].SelectSingleNode('..').RemoveChild($Messages[$Index]) | Out-Null
$Messages[$Index].Deleted = 'True'
$xmlMail.Save($XMLMAILFILE)
$Global:Mail = $Global:xmlMail.Mail
Respond "Deleted mail $($Index + 1) from $From on $($Sent.PlayerTime) $($Sent.Timezone)" $Player $Private
}
Function SendMail ([String]$From, [String]$To, [String]$Body, [Boolean]$Private = $False)
{
$Inbox = $Mail.$To
If (!($Inbox))
{
$Inbox = $xmlMail.CreateElement($To)
$xmlMail.SelectSingleNode('Mail').AppendChild($Inbox)
$xmlMail.Save($XMLMAILFILE)
$Global:Mail = $Global:xmlMail.Mail
}
$Message = $xmlMail.CreateElement('Message')
$Message.SetAttribute('From', $From)
$Message.SetAttribute('Sent', (Get-Date (Get-Date).ToUniversalTime() -Format u))
$Message.SetAttribute('Read', 'False')
$Message.SetAttribute('Deleted', 'False')
$BodyNode = $xmlMail.CreateElement('Body')
$BodyNode.InnerText = $Body
$Message.AppendChild($BodyNode)
$Inbox.AppendChild($Message)
$xmlMail.Save($XMLMAILFILE)
$Global:Mail = $Global:xmlMail.Mail
$Player = GetPlayer($To)
If ($Player['LastConnection'] -eq $Null) { $Connected = "`(WARNING: $To has never connected before`)" }
If ($Players.$To) { CheckMail $To $True }
Respond "Mail sent to $To $Connected" $From $Private
}
Function ToPlayerTime ([Datetime]$Original, [String]$Name)
{
$Player = GetPlayer($Name)
If ($Player['ActiveTimeBias'] -ne [DBNull]::Value)
{
$dblBiasHours =$Player['ActiveTimeBias'].Split(':')[0]
$dblBiasMinutes = $Player['ActiveTimeBias'].Split(':')[1]
$strBias = "$dblBiasHours"
If ($dblBiasMinutes) { $strBias = $strBias + "`:$dblBiasMinutes" }
If (!($strBias.StartsWith('-'))) { $strBias = '+' + $strBias }
ElseIf ($dblBiasMinutes) { $dblBiasMinutes = '-' + $dblBiasMinutes }
}
[Hashtable]$Return = @{}
$Return.UTC = $Original.ToUniversalTime()
$Return.UTC_ISO8601 = Get-Date $Original.ToUniversalTime() -Format u
$Return.PlayerTime = $Original.ToUniversalTime()
If ($dblBiasHours) { $Return.PlayerTime = ($Return.PlayerTime).AddHours($dblBiasHours) }
If ($dblBiasMinutes) { $Return.PlayerTime = ($Return.PlayerTime).AddMinutes($dblBiasMinutes) }
$Return.Timezone = "GMT$strBias"
Return $Return
}
Function MemberOf ([String]$Group, [String]$Player)
{
$Command = New-Object System.Data.SqlClient.SqlCommand("IsMember", $SQL)
$Command.CommandType = [System.Data.CommandType]::StoredProcedure
$GroupName = New-Object System.Data.SqlClient.SqlParameter('@GroupName', [System.Data.DbType]::String)
$GroupName.Direction = [System.Data.ParameterDirection]::Input
$GroupName.Value = $Group
[Void]$Command.Parameters.Add($GroupName)
$PlayerName = New-Object System.Data.SqlClient.SqlParameter('@PlayerName', [System.Data.DbType]::String)
$PlayerName.Direction = [System.Data.ParameterDirection]::Input
$PlayerName.Value = $Player
[Void]$Command.Parameters.Add($PlayerName)
$RC = New-Object System.Data.SqlClient.SqlParameter('@RC', [System.Data.DbType]::Int)
$RC.Direction = [System.Data.ParameterDirection]::ReturnValue
[Void]$Command.Parameters.Add($RC)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$Command.ExecuteReader()
$SQL.Close()
If ($RC.Value -ne 1) { Return $False }
Return $True
}
Function ModifyMembers ([String]$Action, [String]$PlayerName, [String]$GroupName, [String]$Comments, [String]$Requestor)
{
#-- Group must exist already before it can be modified
$Command = New-Object System.Data.SqlClient.SqlCommand("SELECT 1 FROM Groups WHERE Name = '$GroupName'", $SQL)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$Exists = $Command.ExecuteScalar()
$SQL.Close()
If (!$Exists) { Return "$GroupName group does not exist." }
$Member = Memberof $GroupName $PlayerName
Switch -regex ($Action.ToLower())
{
'^a[d]?[d]?$'
{
If ($Member) { Return "$PlayerName is already a member of $GroupName group." }
SetPlayer $PlayerName
$Command = New-Object System.Data.SqlClient.SqlCommand("
INSERT INTO PlayersGroups (Players_ID, Groups_ID, Added, AddedBy, Comments)
SELECT
(SELECT ID FROM Players WHERE Name = @PN)
, (SELECT ID FROM Groups WHERE Name = @GN)
, GETUTCDATE()
, (SELECT ID FROM Players WHERE Name = @R)
, @C
", $SQL)
$PN = New-Object System.Data.SqlClient.SqlParameter('@PN', [System.Data.DbType]::String)
$PN.Direction = [System.Data.ParameterDirection]::Input
$PN.Value = $PlayerName
[Void]$Command.Parameters.Add($PN)
$GN = New-Object System.Data.SqlClient.SqlParameter('@GN', [System.Data.DbType]::String)
$GN.Direction = [System.Data.ParameterDirection]::Input
$GN.Value = $GroupName
[Void]$Command.Parameters.Add($GN)
$R = New-Object System.Data.SqlClient.SqlParameter('@R', [System.Data.DbType]::String)
$R.Direction = [System.Data.ParameterDirection]::Input
$R.Value = $Requestor
[Void]$Command.Parameters.Add($R)
$C = New-Object System.Data.SqlClient.SqlParameter('@C', [System.Data.DbType]::String)
$C.Direction = [System.Data.ParameterDirection]::Input
$C.Value = $Comments
[Void]$Command.Parameters.Add($C)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$Affected = $Command.ExecuteNonQuery()
$SQL.Close()
If ($Affected -eq 1) { Return "$PlayerName added to $GroupName group." }
Else { Return "Error adding $PlayerName to $GroupName group." }
}
'^r[e]?[m]?[o]?[v]?[e]?$'
{
If (!$Member) { Return "$PlayerName is not a member of $GroupName group." }
$Command = New-Object System.Data.SqlClient.SqlCommand("
DELETE FROM PlayersGroups
WHERE
Players_ID = (SELECT ID FROM Players WHERE Name = @PN)
AND Groups_ID = (SELECT ID FROM Groups WHERE Name = @GN)
", $SQL)
$PN = New-Object System.Data.SqlClient.SqlParameter('@PN', [System.Data.DbType]::String)
$PN.Direction = [System.Data.ParameterDirection]::Input
$PN.Value = $PlayerName
[Void]$Command.Parameters.Add($PN)
$GN = New-Object System.Data.SqlClient.SqlParameter('@GN', [System.Data.DbType]::String)
$GN.Direction = [System.Data.ParameterDirection]::Input
$GN.Value = $GroupName
[Void]$Command.Parameters.Add($GN)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$Affected = $Command.ExecuteNonQuery()
$SQL.Close()
If ($Affected -eq 1) { Return "$PlayerName removed from $GroupName group." }
Else { Return "Error removing $PlayerName from $GroupName group." }
}
}
}
Function timAutoSave_Elapsed ([System.Object]$sender, [System.Timers.ElapsedEventArgs]$e)
{
If (SDP.HasExited)
{
($sender -As [System.Timers.Timer]).Stop()
Unregister-Event 'AutoSave'
Remove-Job 'AutoSave'
Return
}
$Global:timAutoSave.Interval = (GetConfiguration('AutoSave')) * 60 * 1000
$Global:TimerStarts.Save = Get-Date
SetStatus 'LastSaveRequest'
ProcessTask 'Save'
}
Function timAutoBackup_Elapsed ([System.Object]$sender, [System.Timers.ElapsedEventArgs]$e)
{
If (SDP.HasExited)
{
($sender -As [System.Timers.Timer]).Stop()
Unregister-Event 'AutoBackup'
Remove-Job 'AutoBackup'
Return
}
$Global:timAutoBackup.Interval = (GetConfiguration('AutoBackup')) * 60 * 1000
$Global:TimerStarts.Backup = Get-Date
SetStatus 'LastBackupRequest'
ProcessTask 'Backup'
}
Function timAutoImages_Elapsed ([System.Object]$sender, [System.Timers.ElapsedEventArgs]$e)
{
If (SDP.HasExited)
{
($sender -As [System.Timers.Timer]).Stop()
Unregister-Event 'AutoImages'
Remove-Job 'AutoImages'
Return
}
$Global:timAutoImages.Interval = (GetConfiguration('AutoImages')) * 60 * 1000
$Global:TimerStarts.Images = Get-Date
SetStatus 'LastImagesRequest'
ProcessTask 'Update Images'
}
Function timAutoPrune_Elapsed ([System.Object]$sender, [System.Timers.ElapsedEventArgs]$e)
{
If (SDP.HasExited)
{
($sender -As [System.Timers.Timer]).Stop()
Unregister-Event 'AutoPrune'
Remove-Job 'AutoPrune'
Return
}
$Global:timAutoPrune.Interval = (GetConfiguration('AutoPrune')) * 60 * 1000
$Global:TimerStarts.Prune = Get-Date
SetStatus 'LastPruneRequest'
ProcessTask 'Prune'
}
Function ProcessTask ($Task, [Boolean]$blnForceNext = $False)
{
#Format task to hashtable if simple string
If ($Task) { If ($Task.GetType().Name -eq 'String') { $Task = @{ Command = $Task } } }
#Add task to queue if not already in there
If ($Task -And ($blnForceNext -eq $False))
{
ForEach ($i In $Global:TaskQueue)
{
If (($i.Command -eq $Task.Command) -And ($i.Parameters -eq $Task.Parameters)) { $blnExists = $True; Break }
}
If ($blnExists -ne $True)
{
If (!($Task.Private)) { $Task.Private = $False }
$Global:TaskQueue.Enqueue($Task)
}
}
#Ensure retry timer is configured if a task is already in progress
If (($Global:TaskInProgress -eq $True) -And ($blnForceNext -eq $False))
{
If ($Global:timTaskRetry.Enabled -ne $True)
{
$Global:timTaskRetry = New-Object System.Timers.Timer
$Global:timTaskRetry.Interval = 5000
Register-ObjectEvent $timTaskRetry 'Elapsed' -SourceIdentifier TaskRetry -Action { timTaskRetry_Elapsed @Args } | Out-Null
$Global:timTaskRetry.Start()
}
Return
}
#Exit and cancel retry timer if empty queue
If (($Global:TaskQueue.Count -eq 0) -And ($Global:timTaskRetry.Enabled -eq $True))
{
$Global:timTaskRetry.Stop()
Unregister-Event -SourceIdentifier 'TaskRetry'
Remove-Job -Name 'TaskRetry'
$Global:TaskInProgress = $False
Return
}
$Global:TaskInProgress = $True
$Task = $Global:TaskQueue.Peek()
If ($blnForceNext -eq $True) { $Task.Command = "$($Task.Command.Split('.')[0]).$([Int]($Task.Command.Split('.')[1]) + 1)" }
Switch ($Task.Command.ToLower())
{
'save'
{
ForceSave
$Global:TaskQueue.Dequeue() | Out-Null
$Global:TaskInProgress = $False
}
'backup'
{
ForceSave
MCS 'save-off'
}
'backup.1'
{
$strNow = Get-Date -Date (Get-Date).ToUniversalTime() -Format 'yyyyMMddHHmmss\Z'
$strDestination = "$(GetConfiguration('Backups'))\$strNow.zip"
$prcZip = New-Object System.Diagnostics.Process
$prcZip.StartInfo.FileName = GetConfiguration('BackupProgram')
$prcZip.StartInfo.Arguments = (GetConfiguration('BackupProgramArguments')).Replace('%SOURCE%', (GetConfiguration('World'))).Replace('%DESTINATION%', $strDestination)
$prcZip.StartInfo.UseShellExecute = $False
$prcZip.StartInfo.WorkingDirectory = $strScriptPath
$prcZip.EnableRaisingEvents = $True
Register-ObjectEvent $prcZip 'Exited' -SourceIdentifier 'Zip.Exited' -Action { prcZip_Exited @Args }
$prcZip.Start()
}
'backup.2'
{
MCS 'save-on'
Respond 'This world has just been backed up.' $Task.Requestor $Task.Private
SetStatus 'LastBackup'
$Global:TaskQueue.Dequeue() | Out-Null
$Global:TaskInProgress = $False
}
'update images'
{
$Global:datImagesStarted = Get-Date
Respond 'Updating map images...' $Task.Requestor $Task.Private
ForceSave
MCS 'save-off'
}
'update images.1'
{
If ($Task.Parameters)
{
UpdateImages @{ $Task.Parameters = $Global:Images.($Task.Parameters) }
}
Else
{
$strNow = Get-Date -Date ($Global:datImagesStarted).ToUniversalTime() -Format 'yyyyMMddHHmmss\Z'
UpdateImages $Global:Images "$(GetConfiguration('Images'))\Archive\$strNow"
}
}
'prune'
{
Prune
$Global:TaskQueue.Dequeue() | Out-Null
$Global:TaskInProgress = $False
}
Default
{
Write-Host "ERROR: Unrecognized task of ""$($Task.Command)""."
$Global:TaskQueue.Dequeue() | Out-Null
$Global:TaskInProgress = $False
}
}
Trap
{
Write-Host "Error in ProcessTask" -ForegroundColor Red
Write-Host $_ -ForegroundColor Red
Write-Host "Ln $($_.InvocationInfo.ScriptLineNumber) Col $($_.InvocationInfo.OffsetInLine): $($_.InvocationInfo.Line)" -ForegroundColor Red
Break #Continue
}
}
Function Prune ()
{
$PruneBackupsDays = GetConfiguration('PruneBackupsDays')
If ($PruneBackupsDays -eq [DBNull]::Value) { $PruneBackupsDays = 0 }
If ($PruneBackupsDays -gt 0)
{
$Backups = GetConfiguration('Backups')
If (Test-Path $Backups)
{
$DeleteBackupsOlderThen = (Get-Date).AddDays(-$PruneBackupsDays)
Get-ChildItem $Backups *.zip `
| Where-Object { $_.LastWriteTimeUTC -le $DeleteBackupsOlderThen.ToUniversalTime() } `
| Remove-Item -Force
}
}
$PruneImagesDays = GetConfiguration('PruneImagesDays')
If ($PruneImagesDays -eq [DBNull]::Value) { $PruneImagesDays = 0 }
If ($PruneImagesDays -gt 0)
{
$DeleteImagesOlderThen = (Get-Date).AddDays(-$PruneImagesDays)
$Archive = (GetConfiguration('Images')) + '\Archive'
If (Test-Path $Archive)
{
#Remove old folders from Archive
Get-ChildItem $Archive `
| Where-Object { ($_.psIsContainer -eq $True) -and ($_.LastWriteTimeUTC -le $DeleteImagesOlderThen.ToUniversalTime()) } `
| Remove-Item -Force -Recurse
}
$Updates = (GetConfiguration('Images')) + '\Updates'
If (Test-Path $Updates)
{
#Remove old folders from Updates
$Updates = 'D:\Documents\Personal\Games\Minecraft\Inetpub\www\maps\Updates'
Get-ChildItem $Updates `
| Where-Object { ($_.psIsContainer -eq $True) -and ($_.LastWriteTimeUTC -le $DeleteImagesOlderThen.ToUniversalTime()) } `
| Remove-Item -Force -Recurse
}
}
Trap
{
Write-Host "Error in Prune" -ForegroundColor Red
Write-Host $_ -ForegroundColor Red
Write-Host "Ln $($_.InvocationInfo.ScriptLineNumber) Col $($_.InvocationInfo.OffsetInLine): $($_.InvocationInfo.Line)" -ForegroundColor Red
Continue
}
}
Function ForceSave ()
{
#--Check global variable as two requests back to back won't update database quick enough
If ($Global:LastSave -ne $Null) {
If ((New-TimeSpan $Global:LastSave (Get-Date)).TotalMinutes -lt 5) { Return }
}
#--Check database
If ( (New-TimeSpan ((GetStatus('LastSave')).ToLocalTime()) (Get-Date)).TotalMinutes -lt 5 ) { Return }
$Global:LastSave = Get-Date
MCS 'say Forcing save...'
MCS 'save-all'
}
Function prcZip_Exited ([System.Object]$sender, $e)
{
Unregister-Event -SourceIdentifier 'Zip.Exited'
Remove-Job -Name 'Zip.Exited'
ProcessTask 'backup.2' $True
}
Function timTaskRetry_Elapsed ([System.Object]$sender, [System.Timers.ElapsedEventArgs]$e)
{
ProcessTask
}
Function UpdateImages ($hshImages, [String]$strOutput)
{
If ($hshImages)
{
If ($strOutput) { $Global:strImagesOutput = $strOutput }
Else
{
$strNow = Get-Date -Date ($Global:datImagesStarted).ToUniversalTime() -Format 'yyyyMMddHHmmss\Z'
$Global:strImagesOutput = (GetConfiguration('Images')) + '\Updates\' + $strNow
}
New-Item $Global:strImagesOutput -ItemType 'Directory' | Out-Null
$Global:queImages = New-Object System.Collections.Queue
ForEach ($i In $hshImages.Keys)
{
If (!($hshImages.$i.Parameters.Contains("--show-signs")) -and ($strOutput))
{
$hshImages.$i.Parameters += " --write-json `"C:\Minecraft\Inetpub\www\maps\c10t\$($hshImages.$i.File).json`"" `
+ " --show-signs=* --ttf-path `"c:\windows\fonts\lucon.ttf`""
}
$hshImages.$i.Requestor = $Requestor
$hshImages.$i.Private = $Private
$hshImages.$i.Abbreviation = $i
$Global:queImages.Enqueue($hshImages.$i)
}
$Global:ImageCount = 0
If ($hshImages.Keys.Count -eq 1) { $Global:SingleImage = $Global:Images.$($hshImages.Keys).File }
}
If ($Global:queImages.Count -eq 0)
{
MCS 'save-on'
#Record and notify players of completion
If ($Global:SingleImage)
{
$strUpdate = "Map image $Global:SingleImage"
If ($Global:ImageCount -ne 1) { $strUpdate += ' had an error while being' }
}
Else
{
SetStatus 'LastImages'
$strUpdate = "$Global:ImageCount Map images"
Get-Job | Where-Object { $_.Name -eq 'Google Map Update' } | Remove-Job -Force
Start-Job (GetConfiguration('ImagesTilesScript')) -Name 'Google Map Update' | Out-Null
}
Respond ("$strUpdate updated. `($(Duration $Global:datImagesStarted)`) $(GetConfiguration('HomeURL'))") `
$Global:TaskQueue.Peek().Requestor $Global:TaskQueue.Peek().Private
$Global:SingleImage = ''
#Finalize task
$Global:TaskQueue.Dequeue() | Out-Null
$Global:TaskInProgress = $False
[System.Net.HttpWebRequest]::Create('http://mc.rjump.com/maps/').BeginGetResponse($Null, $Null)
Return
}
$strFile = $Global:strImagesOutput + '\' + $Global:queImages.Peek().File
$strParameters = $Global:queImages.Peek().Parameters
$Abbreviation = $Global:queImages.Peek().Abbreviation
$Global:queImages.Dequeue() | Out-Null
$prcImage = New-Object System.Diagnostics.Process
$prcImage.StartInfo.FileName = GetConfiguration('ImagesProgram')
$prcImage.StartInfo.Arguments = "-w ""$(GetConfiguration('World'))"" -o ""$strFile"" $strParameters"
$prcImage.StartInfo.WorkingDirectory = $strScriptPath
$prcImage.StartInfo.UseShellExecute = $False
$prcImage.EnableRaisingEvents = $True
Register-ObjectEvent $prcImage 'Exited' -SourceIdentifier 'Image.Exited' -Action { prcImage_Exited @Args $Event.MessageData } -MessageData @{ Abbreviation = $Abbreviation; Path = $Global:strImagesOutput } | Out-Null
$prcImage.Start() | Out-Null
Trap
{
Write-Host "Error in Update Images" -ForegroundColor Red
Write-Host $_ -ForegroundColor Red
Write-Host "Ln $($_.InvocationInfo.ScriptLineNumber) Col $($_.InvocationInfo.OffsetInLine): $($_.InvocationInfo.Line)" -ForegroundColor Red
#Write-Error 'Error Processing Standard Error Stream Test' -ErrorID STDERR1 -TargetObject $_
Break #Continue
}
}
Function prcImage_Exited ([System.Diagnostics.Process]$sender, [System.EventArgs]$e, $MessageData)
{
Unregister-Event -SourceIdentifier 'Image.Exited'
Remove-Job -Name 'Image.Exited'
#-- If no errors on exit, then update database with location for image
If ($sender.ExitCode -eq 0)
{
$Command = New-Object System.Data.SqlClient.SqlCommand("UPDATE Images SET Latest = '$($MessageData.Path)' WHERE Abbreviation = '$($MessageData.Abbreviation)'", $SQL)
If ($SQL.State -eq 'Closed') { $SQL.Open() }
[Void]$Command.ExecuteNonQuery()
$SQL.Close()
$Global:ImageCount++
}
UpdateImages
Trap
{
Write-Host "Error in prcImage_Exited" -ForegroundColor Red
Write-Host $_ -ForegroundColor Red
Write-Host "Ln $($_.InvocationInfo.ScriptLineNumber) Col $($_.InvocationInfo.OffsetInLine): $($_.InvocationInfo.Line)" -ForegroundColor Red
Break #Continue
}
}
Function Duration ($In)
{
If ($In.GetType().Name -ne 'TimeSpan') { $In = New-TimeSpan $In }
$Out = ''
If ($In.Days -ne 0) { $Out += [String]$In.Days + 'd ' }
If ($In.Hours -ne 0) { $Out += [String]$In.Hours + 'h ' }
If ($In.Minutes -ne 0) { $Out += [String]$In.Minutes + 'm ' }
Return ($Out + $In.Seconds + 's')
}
Function IsNumeric ($x) { Return [System.Int32]::TryParse($x, [Ref]0) }
Function Test([String]$Command)
{
ProcessCommand (Get-Date) 'EdGruberman' $Command $True
}
$Global:Configuration = 'Workstation'
$Global:strScriptPath = Split-Path $MyInvocation.MyCommand.Path
$Global:XMLCFGFILE = "$strScriptPath\MCS Configuration.xml"
$Global:XMLMAILFILE = "$strScriptPath\MCS Mail.xml"
$Global:xmlMail = [XML](Get-Content $XMLMAILFILE)
$Global:Mail = $Global:xmlMail.Mail
$xmlConfig = [XML](Get-Content $XMLCFGFILE)
$Builder = New-Object System.Data.SqlClient.SqlConnectionStringBuilder
$Builder['Data Source'] = $xmlConfig.Configuration.Database.Source
$Builder['Initial Catalog'] = $xmlConfig.Configuration.Database.Name
$Builder['Integrated Security'] = $True
$Builder['MultipleActiveResultSets'] = $True
$Global:SQL = New-Object System.Data.SqlClient.SqlConnection($Builder.ConnectionString)
#-- Get image definitions
$ImagesFont = GetConfiguration('ImagesFont')
If ($SQL.State -eq 'Closed') { $SQL.Open() }
$ImagesSQL = (New-Object System.Data.SqlClient.SqlCommand('SELECT Abbreviation, FileName, Parameters FROM Images', $SQL)).ExecuteReader()
$Images = @{}
While ( $ImagesSQL.Read() )
{ $Images.($ImagesSQL['Abbreviation']) = @{ File = $ImagesSQL['FileName']; Parameters = $ImagesSQL['Parameters'].Replace('%FONT%', $ImagesFont) } }
$ImagesSQL.Close()
$SQL.Close()
Trap
{
Write-Host $_
Continue
}
MCS.Start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment