Finished BackupServer and UpdateServer

This commit is contained in:
Brett Hewitson 2021-12-05 01:56:11 +10:00
parent 824daed0d1
commit 0f3c6e6be9
28 changed files with 618 additions and 216 deletions

View file

@ -173,6 +173,7 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Delegates\ServerStatusChangeDelegate.cs" />
<Compile Include="Enums\LevelProgression.cs" />
<Compile Include="Enums\LogEventType.cs" />
<Compile Include="Enums\NPCSpawnContainerType.cs" />
@ -196,7 +197,7 @@
<Compile Include="Lib\Serialization\IniSections.cs" />
<Compile Include="Lib\Serialization\SystemIniFile.cs" />
<Compile Include="Lib\Model\PlayerListParameters.cs" />
<Compile Include="Lib\ServerBranchSnapshot.cs" />
<Compile Include="Lib\BranchSnapshot.cs" />
<Compile Include="Lib\ServerPlayers.cs" />
<Compile Include="Lib\ServerProfileSnapshot.cs" />
<Compile Include="Lib\ViewConverters\EnumDescriptionTypeConverter.cs" />

View file

@ -0,0 +1,6 @@
using ServerManagerTool.Enums;
namespace ServerManagerTool.Delegates
{
public delegate void ServerStatusChangeDelegate(ServerStatus serverStatus);
}

View file

@ -10,5 +10,6 @@
Backup,
Shutdown,
Restart,
Update,
}
}

View file

@ -786,6 +786,9 @@
<sys:String x:Key="MainWindow_SteamCmd_FailedTitle">Reinstall SteamCMD Error</sys:String>
<sys:String x:Key="MainWindow_SteamCmd_FailedLabel">An error occured while trying to reinstall SteamCMD. This has left SteamCmd in an unstable state, try reinstalling again or please report this.\r\nException: {0}</sys:String>
<sys:String x:Key="MainWindow_DiscordBot_RunningCommandsTitle">Discord Bot Running Commands</sys:String>
<sys:String x:Key="MainWindow_DiscordBot_RunningCommandsLabel">The discord bot has one or more running commands, do you want to continue shutting down the server manager?</sys:String>
<sys:String x:Key="MainWindow_ServerStatus_StartServerActionTitle">Start Server Confirmation</sys:String>
<sys:String x:Key="MainWindow_ServerStatus_StartServerActionLabel">You are about to start the server, do you want to continue?</sys:String>
<sys:String x:Key="MainWindow_ServerStatus_ShutdownServerActionTitle">Shutdown Server Confirmation</sys:String>
@ -5547,12 +5550,17 @@
<sys:String x:Key="DiscordBot_CommandNotImplemented">Command '{0}' has not been implemented.</sys:String>
<sys:String x:Key="DiscordBot_CommandUnknown">Unknown command '{0}'.</sys:String>
<sys:String x:Key="DiscordBot_CommandRunning">Another command is currently running.</sys:String>
<sys:String x:Key="DiscordBot_CommandProfileMissing">The command requires a profile id.</sys:String>
<sys:String x:Key="DiscordBot_CommandProfileNotFound">Profile id {0} not found or is not associated with the channel.</sys:String>
<sys:String x:Key="DiscordBot_CommandRunning">Another command is currently being processed.</sys:String>
<sys:String x:Key="DiscordBot_CommandRunningProfile">Another command '{0}' is currently running against profile '{1}'.</sys:String>
<sys:String x:Key="DiscordBot_CommandInfoFailed">Call to the server '{0}' failed.</sys:String>
<sys:String x:Key="DiscordBot_ProfileMissing">The '{0}' command requires a profile id.</sys:String>
<sys:String x:Key="DiscordBot_ProfileNotFound">Profile '{0}' was not found or is not associated with the channel.</sys:String>
<sys:String x:Key="DiscordBot_ProfileBadStatus">Profile '{0}' must be '{1}' to perform the command.</sys:String>
<sys:String x:Key="DiscordBot_ProfileUpdating">Profile '{0}' is currently being updated.</sys:String>
<sys:String x:Key="DiscordBot_InfoFailed">Call to server '{0}' failed.</sys:String>
<sys:String x:Key="DiscordBot_BackupRequested">A backup request for server '{0}' has been sent.</sys:String>
<sys:String x:Key="DiscordBot_UpdateRequested">An update request for server '{0}' has been sent.</sys:String>
<sys:String x:Key="DiscordBot_CountLabel">Count:</sys:String>
<sys:String x:Key="DiscordBot_MapLabel">Map:</sys:String>

View file

@ -3,15 +3,37 @@ using System.Collections.Generic;
namespace ServerManagerTool.Lib
{
public class ServerBranchSnapshot
public class BranchSnapshot
{
private BranchSnapshot()
{
}
public string BranchName = string.Empty;
public string BranchPassword = string.Empty;
public static BranchSnapshot Create(ServerProfile profile)
{
return new BranchSnapshot
{
BranchName = profile.BranchName,
BranchPassword = profile.BranchPassword
};
}
public static BranchSnapshot Create(ServerProfileSnapshot profile)
{
return new BranchSnapshot
{
BranchName = profile.BranchName,
BranchPassword = profile.BranchPassword
};
}
}
public class ServerBranchSnapshotComparer : IEqualityComparer<ServerBranchSnapshot>
public class BranchSnapshotComparer : IEqualityComparer<BranchSnapshot>
{
public bool Equals(ServerBranchSnapshot x, ServerBranchSnapshot y)
public bool Equals(BranchSnapshot x, BranchSnapshot y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
@ -24,7 +46,7 @@ namespace ServerManagerTool.Lib
return x.BranchName == y.BranchName;
}
public int GetHashCode(ServerBranchSnapshot snapshot)
public int GetHashCode(BranchSnapshot snapshot)
{
//Check whether the object is null
if (snapshot is null) return 0;

View file

@ -94,7 +94,7 @@ namespace ServerManagerTool.Lib
await this.Runtime.StopAsync();
}
public async Task<bool> UpgradeAsync(CancellationToken cancellationToken, bool updateServer, ServerBranchSnapshot branch, bool validate, bool updateMods, ProgressDelegate progressCallback)
public async Task<bool> UpgradeAsync(CancellationToken cancellationToken, bool updateServer, BranchSnapshot branch, bool validate, bool updateMods, ProgressDelegate progressCallback)
{
await this.Runtime.AttachToProfile(this.Profile);
var success = await this.Runtime.UpgradeAsync(cancellationToken, updateServer, branch, validate, updateMods, progressCallback);

View file

@ -2,6 +2,7 @@
using ServerManagerTool.Common.Lib;
using ServerManagerTool.Common.Model;
using ServerManagerTool.Common.Utils;
using ServerManagerTool.Delegates;
using ServerManagerTool.Enums;
using ServerManagerTool.Plugin.Common;
using ServerManagerTool.Utils;
@ -105,6 +106,7 @@ namespace ServerManagerTool.Lib
public int ShutdownInterval = Config.Default.ServerShutdown_GracePeriod;
public ProgressDelegate ProgressCallback = null;
public ProcessWindowStyle SteamCMDProcessWindowStyle = ProcessWindowStyle.Minimized;
public ServerStatusChangeDelegate ServerStatusChangeCallback = null;
public ServerApp(bool resetStartTime = false)
{
@ -264,7 +266,15 @@ namespace ServerManagerTool.Lib
if (updateServer)
{
UpgradeLocal(true, cancellationToken, true);
try
{
ServerStatusChangeCallback?.Invoke(ServerStatus.Updating);
UpgradeLocal(true, cancellationToken, true);
}
finally
{
ServerStatusChangeCallback?.Invoke(ServerStatus.Stopped);
}
}
if (ExitCode != EXITCODE_NORMALEXIT)
@ -2869,7 +2879,7 @@ namespace ServerManagerTool.Lib
return ExitCode;
}
public int PerformProfileUpdate(ServerBranchSnapshot branch, ServerProfileSnapshot profile)
public int PerformProfileUpdate(BranchSnapshot branch, ServerProfileSnapshot profile)
{
_profile = profile;
@ -2945,7 +2955,7 @@ namespace ServerManagerTool.Lib
return ExitCode;
}
public int PerformServerBranchUpdate(ServerBranchSnapshot branch)
public int PerformServerBranchUpdate(BranchSnapshot branch)
{
if (branch == null)
return EXITCODE_NORMALEXIT;
@ -3233,8 +3243,8 @@ namespace ServerManagerTool.Lib
if (exitCode == EXITCODE_NORMALEXIT)
{
var branches = _profiles.Keys.Where(p => p.EnableAutoUpdate).Select(p => new ServerBranchSnapshot() { BranchName = p.BranchName, BranchPassword = p.BranchPassword}).Distinct(new ServerBranchSnapshotComparer()).ToArray();
var exitCodes = new ConcurrentDictionary<ServerBranchSnapshot, int>();
var branches = _profiles.Keys.Where(p => p.EnableAutoUpdate).Select(p => BranchSnapshot.Create(p)).Distinct(new BranchSnapshotComparer()).ToArray();
var exitCodes = new ConcurrentDictionary<BranchSnapshot, int>();
// update the server cache for each branch
if (Config.Default.AutoUpdate_ParallelUpdate)

View file

@ -7,6 +7,10 @@ namespace ServerManagerTool.Lib
{
public class ServerProfileSnapshot
{
private ServerProfileSnapshot()
{
}
public string ProfileId;
public string ProfileName;
public string InstallDirectory;

View file

@ -33,7 +33,7 @@ namespace ServerManagerTool.Lib
public event EventHandler StatusUpdate;
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
private static readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
private readonly List<PropertyChangeNotifier> profileNotifiers = new List<PropertyChangeNotifier>();
private Process serverProcess;
private IAsyncDisposable updateRegistration;
@ -439,7 +439,7 @@ namespace ServerManagerTool.Lib
}
CheckServerWorldFileExists();
UpdateServerStatus(ServerStatus.Initializing, this.Availability, false);
UpdateServerStatus(ServerStatus.Initializing, false);
try
{
@ -498,12 +498,12 @@ namespace ServerManagerTool.Lib
}
}
public async Task<bool> UpgradeAsync(CancellationToken cancellationToken, bool updateServer, ServerBranchSnapshot branch, bool validate, bool updateMods, ProgressDelegate progressCallback)
public async Task<bool> UpgradeAsync(CancellationToken cancellationToken, bool updateServer, BranchSnapshot branch, bool validate, bool updateMods, ProgressDelegate progressCallback)
{
return await UpgradeAsync(cancellationToken, updateServer, branch, validate, updateMods, null, progressCallback);
}
public async Task<bool> UpgradeAsync(CancellationToken cancellationToken, bool updateServer, ServerBranchSnapshot branch, bool validate, bool updateMods, string[] updateModIds, ProgressDelegate progressCallback)
public async Task<bool> UpgradeAsync(CancellationToken cancellationToken, bool updateServer, BranchSnapshot branch, bool validate, bool updateMods, string[] updateModIds, ProgressDelegate progressCallback)
{
if (updateServer && !Environment.Is64BitOperatingSystem)
{
@ -520,7 +520,7 @@ namespace ServerManagerTool.Lib
bool isNewInstallation = this.Status == ServerStatus.Uninstalled;
UpdateServerStatus(ServerStatus.Updating, Availability, false);
UpdateServerStatus(ServerStatus.Updating, false);
// Run the SteamCMD to install the server
var steamCmdFile = SteamCmdUpdater.GetSteamCmdFile(Config.Default.DataDir);
@ -957,7 +957,7 @@ namespace ServerManagerTool.Lib
finally
{
this.lastModStatusQuery = DateTime.MinValue;
UpdateServerStatus(ServerStatus.Stopped, Availability, false);
UpdateServerStatus(ServerStatus.Stopped, false);
}
}
@ -993,6 +993,11 @@ namespace ServerManagerTool.Lib
this.lastModStatusQuery = DateTime.MinValue;
}
public void UpdateServerStatus(ServerStatus serverStatus, bool sendAlert)
{
UpdateServerStatus(serverStatus, Availability, sendAlert);
}
public void UpdateServerStatus(ServerStatus serverStatus, AvailabilityStatus availabilityStatus, bool sendAlert)
{
this.Status = serverStatus;
@ -1006,32 +1011,29 @@ namespace ServerManagerTool.Lib
public void UpdateServerStatusString()
{
switch (Status)
StatusString = GetServerStatusString(Status);
}
public static string GetServerStatusString(ServerStatus status)
{
switch (status)
{
case ServerStatus.Initializing:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusInitializingLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusInitializingLabel");
case ServerStatus.Running:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusRunningLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusRunningLabel");
case ServerStatus.Stopped:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusStoppedLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusStoppedLabel");
case ServerStatus.Stopping:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusStoppingLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusStoppingLabel");
case ServerStatus.Uninstalled:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusUninstalledLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusUninstalledLabel");
case ServerStatus.Unknown:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusUnknownLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusUnknownLabel");
case ServerStatus.Updating:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusUpdatingLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusUpdatingLabel");
default:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusUnknownLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusUnknownLabel");
}
}

View file

@ -1,11 +1,15 @@
using QueryMaster;
using ServerManagerTool.Common.Utils;
using ServerManagerTool.DiscordBot.Enums;
using ServerManagerTool.Enums;
using ServerManagerTool.Lib;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using WPFSharp.Globalizer;
namespace ServerManagerTool.Utils
@ -15,6 +19,10 @@ namespace ServerManagerTool.Utils
private static readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
private static bool _runningCommand = false;
private static readonly Dictionary<string, CommandType> _currentProfileCommands = new Dictionary<string, CommandType>();
public static bool HasRunningCommands => _currentProfileCommands.Count > 0;
public static IList<string> HandleDiscordCommand(CommandType commandType, string serverId, string channelId, string profileId)
{
// check if incoming values are valid
@ -75,54 +83,68 @@ namespace ServerManagerTool.Utils
{
if (string.IsNullOrWhiteSpace(profileId))
{
return new List<string> { _globalizer.GetResourceString("DiscordBot_CommandProfileMissing") };
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Info) };
}
var serverName = string.Empty;
var serverIp = IPAddress.Loopback;
var queryPort = 0;
TaskUtils.RunOnUIThreadAsync(() =>
// check if another command is being run against the profile
if (_currentProfileCommands.ContainsKey(profileId))
{
var server = ServerManager.Instance.Servers.Where(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID)).FirstOrDefault();
if (server is null)
{
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandProfileNotFound"), profileId));
}
serverName = server.Profile.ServerName;
if (!string.IsNullOrWhiteSpace(server.Profile.ServerIP))
{
IPAddress.TryParse(server.Profile.ServerIP, out serverIp);
}
queryPort = server.Profile.QueryPort;
}).Wait();
List<string> response = new List<string>();
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
}
_currentProfileCommands.Add(profileId, CommandType.Info);
try
{
using (var gameServer = ServerQuery.GetServerInstance(EngineType.Source, new IPEndPoint(serverIp, queryPort)))
var serverName = string.Empty;
var serverIp = IPAddress.Loopback;
var queryPort = 0;
TaskUtils.RunOnUIThreadAsync(() =>
{
var info = gameServer?.GetInfo();
if (info is null)
var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
if (server is null)
{
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_CommandInfoFailed"), serverName));
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
}
else
serverName = server.Profile.ServerName;
if (!string.IsNullOrWhiteSpace(server.Profile.ServerIP))
{
var mapName = _globalizer.GetResourceString($"Map_{info.Map}") ?? info.Map;
response.Add($"```{info.Name}\n{_globalizer.GetResourceString("DiscordBot_MapLabel")} {mapName}\n{_globalizer.GetResourceString("ServerSettings_PlayersLabel")} {info.Players} / {info.MaxPlayers}```");
IPAddress.TryParse(server.Profile.ServerIP, out serverIp);
}
queryPort = server.Profile.QueryPort;
}).Wait();
List<string> response = new List<string>();
try
{
using (var gameServer = ServerQuery.GetServerInstance(EngineType.Source, new IPEndPoint(serverIp, queryPort)))
{
var info = gameServer?.GetInfo();
if (info is null)
{
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_InfoFailed"), serverName));
}
else
{
var mapName = _globalizer.GetResourceString($"Map_{info.Map}") ?? info.Map;
response.Add($"```{info.Name}\n{_globalizer.GetResourceString("DiscordBot_MapLabel")} {mapName}\n{_globalizer.GetResourceString("ServerSettings_PlayersLabel")} {info.Players} / {info.MaxPlayers}```");
}
}
}
}
catch (Exception)
{
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_CommandInfoFailed"), serverName));
}
catch (Exception)
{
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_InfoFailed"), serverName));
}
return response;
return response;
}
finally
{
_currentProfileCommands.Remove(profileId);
}
}
private static IList<string> GetServerList(string channelId)
@ -163,7 +185,63 @@ namespace ServerManagerTool.Utils
private static IList<string> BackupServer(string channelId, string profileId)
{
return new List<string>() { string.Format(_globalizer.GetResourceString("DiscordBot_CommandUnknown"), CommandType.Backup) };
if (string.IsNullOrWhiteSpace(profileId))
{
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Backup) };
}
// check if another command is being run against the profile
if (_currentProfileCommands.ContainsKey(profileId))
{
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
}
_currentProfileCommands.Add(profileId, CommandType.Backup);
ServerProfileSnapshot profile = null;
Task task = null;
try
{
TaskUtils.RunOnUIThreadAsync(() =>
{
var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
if (server is null)
{
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
}
profile = ServerProfileSnapshot.Create(server.Profile);
}).Wait();
List<string> response = new List<string>();
var app = new ServerApp(true)
{
DeleteOldServerBackupFiles = !Config.Default.AutoBackup_EnableBackup,
OutputLogs = false,
SendAlerts = true,
SendEmails = false,
ServerProcess = ServerProcessType.Backup,
};
task = Task.Run(() =>
{
app.PerformProfileBackup(profile);
_currentProfileCommands.Remove(profileId);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_BackupRequested"), profile.ServerName));
return response;
}
finally
{
if (task is null)
{
_currentProfileCommands.Remove(profileId);
}
}
}
private static IList<string> ShutdownServer(string channelId, string profileId)
@ -183,7 +261,87 @@ namespace ServerManagerTool.Utils
private static IList<string> UpdateServer(string channelId, string profileId)
{
return new List<string>() { string.Format(_globalizer.GetResourceString("DiscordBot_CommandUnknown"), CommandType.Update) };
if (string.IsNullOrWhiteSpace(profileId))
{
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Update) };
}
// check if another command is being run against the profile
if (_currentProfileCommands.ContainsKey(profileId))
{
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
}
_currentProfileCommands.Add(profileId, CommandType.Update);
ServerProfileSnapshot profile = null;
bool performRestart = false;
Task task = null;
try
{
TaskUtils.RunOnUIThreadAsync(() =>
{
var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
if (server is null)
{
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
}
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
case ServerStatus.Stopping:
case ServerStatus.Unknown:
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, ServerRuntime.GetServerStatusString(ServerStatus.Stopped)));
case ServerStatus.Running:
performRestart = true;
break;
case ServerStatus.Updating:
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
}
profile = ServerProfileSnapshot.Create(server.Profile);
}).Wait();
List<string> response = new List<string>();
var app = new ServerApp(true)
{
DeleteOldServerBackupFiles = !Config.Default.AutoBackup_EnableBackup,
OutputLogs = false,
SendAlerts = true,
SendEmails = false,
ServerProcess = ServerProcessType.Update,
ServerStatusChangeCallback = (ServerStatus serverStatus) =>
{
TaskUtils.RunOnUIThreadAsync(() =>
{
var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
};
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, performRestart, true, false, CancellationToken.None);
_currentProfileCommands.Remove(profileId);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_UpdateRequested"), profile.ServerName));
return response;
}
finally
{
if (task is null)
{
_currentProfileCommands.Remove(profileId);
}
}
}
}
}

View file

@ -10,7 +10,7 @@
xmlns:com="clr-namespace:ServerManagerTool.Common;assembly=ServerManager.Common"
xmlns:enum="clr-namespace:ServerManagerTool.Enums"
MinWidth="900" MinHeight="600" Width="1100" Height="900" Left="50" Top="50" WindowState="Normal"
Loaded="Window_Loaded" SizeChanged="Window_SizeChanged" StateChanged="Window_StateChanged" LocationChanged="Window_LocationChanged"
Loaded="MainWindow_Loaded" SizeChanged="MainWindow_SizeChanged" StateChanged="MainWindow_StateChanged" LocationChanged="MainWindow_LocationChanged"
Name="Main" Icon="../Art/favicon.ico" Title="{DynamicResource MainWindow_Title}">
<Window.Resources>
<ResourceDictionary>

View file

@ -6,6 +6,7 @@ using ServerManagerTool.Common.Utils;
using ServerManagerTool.Enums;
using ServerManagerTool.Lib;
using ServerManagerTool.Plugin.Common;
using ServerManagerTool.Utils;
using ServerManagerTool.Windows;
using System;
using System.Diagnostics;
@ -169,7 +170,7 @@ namespace ServerManagerTool
GlobalizedApplication.Instance.GlobalizationManager.ResourceDictionaryChangedEvent += ResourceDictionaryChangedEvent;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
//
// Kick off the initialization.
@ -199,15 +200,7 @@ namespace ServerManagerTool
this.scheduledTaskChecker.PostAction(CheckForScheduledTasks).DoNotWait();
}
private void Window_Closed(object sender, EventArgs e)
{
if (sender is Window window)
window.Closed -= Window_Closed;
this.Activate();
}
private void Window_LocationChanged(object sender, EventArgs e)
private void MainWindow_LocationChanged(object sender, EventArgs e)
{
if (this.WindowState == WindowState.Normal)
{
@ -216,7 +209,7 @@ namespace ServerManagerTool
}
}
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (this.WindowState == WindowState.Normal)
{
@ -225,7 +218,7 @@ namespace ServerManagerTool
}
}
private void Window_StateChanged(object sender, EventArgs e)
private void MainWindow_StateChanged(object sender, EventArgs e)
{
if (Config.Default.MainWindow_MinimizeToTray && this.WindowState == WindowState.Minimized)
{
@ -233,8 +226,26 @@ namespace ServerManagerTool
}
}
private void Window_Closed(object sender, EventArgs e)
{
if (sender is Window window)
window.Closed -= Window_Closed;
this.Activate();
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if (DiscordBotHelper.HasRunningCommands)
{
var result = MessageBox.Show(_globalizer.GetResourceString("MainWindow_DiscordBot_RunningCommandsLabel"), _globalizer.GetResourceString("MainWindow_DiscordBot_RunningCommandsTitle"), MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.No)
{
e.Cancel = true;
return;
}
}
base.OnClosing(e);
RCONWindow.CloseAllWindows();
PlayerListWindow.CloseAllWindows();

View file

@ -623,7 +623,7 @@ namespace ServerManagerTool.Windows
await Task.Delay(1000);
var branch = new ServerBranchSnapshot() { BranchName = serverProfile.BranchName, BranchPassword = serverProfile.BranchPassword };
var branch = BranchSnapshot.Create(serverProfile);
return await server.UpgradeAsync(_upgradeCancellationSource.Token, updateServer, branch, true, updateMods, (p, m, n) => { TaskUtils.RunOnUIThreadAsync(() => { window?.AddMessage(m, n); }).DoNotWait(); });
}
else

View file

@ -4266,7 +4266,7 @@ namespace ServerManagerTool
await Task.Delay(1000);
var branch = new ServerBranchSnapshot() { BranchName = this.Server.Profile.BranchName, BranchPassword = this.Server.Profile.BranchPassword };
var branch = BranchSnapshot.Create(this.Server.Profile);
return await this.Server.UpgradeAsync(_upgradeCancellationSource.Token, updateServer, branch, true, updateMods, (p, m, n) => { TaskUtils.RunOnUIThreadAsync(() => { window?.AddMessage(m, n); }).DoNotWait(); });
}
else

View file

@ -160,6 +160,7 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Delegates\ServerStatusChangeDelegate.cs" />
<Compile Include="Lib\Model\PlayerListParameters.cs" />
<Compile Include="Lib\Model\RconParameters.cs" />
<Compile Include="Lib\Serialization\IniFileEntryAttribute.cs" />

View file

@ -0,0 +1,6 @@
using ServerManagerTool.Enums;
namespace ServerManagerTool.Delegates
{
public delegate void ServerStatusChangeDelegate(ServerStatus serverStatus);
}

View file

@ -10,5 +10,6 @@
Backup,
Shutdown,
Restart,
Update,
}
}

View file

@ -628,6 +628,9 @@
<sys:String x:Key="MainWindow_SteamCmd_FailedTitle">Reinstall SteamCMD Error</sys:String>
<sys:String x:Key="MainWindow_SteamCmd_FailedLabel">An error occured while trying to reinstall SteamCMD. This has left SteamCmd in an unstable state, try reinstalling again or please report this.\r\nException: {0}</sys:String>
<sys:String x:Key="MainWindow_DiscordBot_RunningCommandsTitle">Discord Bot Running Commands</sys:String>
<sys:String x:Key="MainWindow_DiscordBot_RunningCommandsLabel">The discord bot has one or more running commands, do you want to continue shutting down the server manager?</sys:String>
<sys:String x:Key="MainWindow_ServerStatus_StartServerActionTitle">Start Server Confirmation</sys:String>
<sys:String x:Key="MainWindow_ServerStatus_StartServerActionLabel">You are about to start the server, do you want to continue?</sys:String>
<sys:String x:Key="MainWindow_ServerStatus_ShutdownServerActionTitle">Shutdown Server Confirmation</sys:String>
@ -1217,12 +1220,17 @@
<sys:String x:Key="DiscordBot_CommandNotImplemented">Command '{0}' has not been implemented.</sys:String>
<sys:String x:Key="DiscordBot_CommandUnknown">Unknown command '{0}'.</sys:String>
<sys:String x:Key="DiscordBot_CommandRunning">Another command is currently running.</sys:String>
<sys:String x:Key="DiscordBot_CommandRunning">Another command is currently being processed.</sys:String>
<sys:String x:Key="DiscordBot_CommandRunningProfile">Another command '{0}' is currently running against profile '{1}'.</sys:String>
<sys:String x:Key="DiscordBot_CommandProfileMissing">The command requires a profile id.</sys:String>
<sys:String x:Key="DiscordBot_CommandProfileNotFound">Profile id {0} not found or is not associated with the channel.</sys:String>
<sys:String x:Key="DiscordBot_ProfileMissing">The '{0}' command requires a profile id.</sys:String>
<sys:String x:Key="DiscordBot_ProfileNotFound">Profile '{0}' was not found or is not associated with the channel.</sys:String>
<sys:String x:Key="DiscordBot_ProfileBadStatus">Profile '{0}' must be '{1}' to perform the command.</sys:String>
<sys:String x:Key="DiscordBot_ProfileUpdating">Profile '{0}' is currently being updated.</sys:String>
<sys:String x:Key="DiscordBot_CommandInfoFailed">Call to the server '{0}' failed.</sys:String>
<sys:String x:Key="DiscordBot_InfoFailed">Call to server '{0}' failed.</sys:String>
<sys:String x:Key="DiscordBot_BackupRequested">A backup request for server '{0}' has been sent.</sys:String>
<sys:String x:Key="DiscordBot_UpdateRequested">An update request for server '{0}' has been sent.</sys:String>
<sys:String x:Key="DiscordBot_CountLabel">Count:</sys:String>
<sys:String x:Key="DiscordBot_MapLabel">Map:</sys:String>

View file

@ -5,8 +5,30 @@ namespace ServerManagerTool.Lib
{
public class BranchSnapshot
{
private BranchSnapshot()
{
}
public string BranchName = string.Empty;
public string BranchPassword = string.Empty;
public static BranchSnapshot Create(ServerProfile profile)
{
return new BranchSnapshot
{
BranchName = profile.BranchName,
BranchPassword = profile.BranchPassword
};
}
public static BranchSnapshot Create(ServerProfileSnapshot profile)
{
return new BranchSnapshot
{
BranchName = profile.BranchName,
BranchPassword = profile.BranchPassword
};
}
}
public class BranchSnapshotComparer : IEqualityComparer<BranchSnapshot>

View file

@ -3,6 +3,7 @@ using ServerManagerTool.Common;
using ServerManagerTool.Common.Lib;
using ServerManagerTool.Common.Model;
using ServerManagerTool.Common.Utils;
using ServerManagerTool.Delegates;
using ServerManagerTool.Enums;
using ServerManagerTool.Plugin.Common;
using ServerManagerTool.Utils;
@ -108,6 +109,7 @@ namespace ServerManagerTool.Lib
public int ShutdownInterval = Config.Default.ServerShutdown_GracePeriod;
public ProgressDelegate ProgressCallback = null;
public ProcessWindowStyle SteamCMDProcessWindowStyle = ProcessWindowStyle.Minimized;
public ServerStatusChangeDelegate ServerStatusChangeCallback = null;
public ServerApp(bool resetStartTime = false)
{
@ -261,7 +263,15 @@ namespace ServerManagerTool.Lib
if (updateServer)
{
UpgradeLocal(true, steamCmdRemoveQuit, cancellationToken, true);
try
{
ServerStatusChangeCallback?.Invoke(ServerStatus.Updating);
UpgradeLocal(true, steamCmdRemoveQuit, cancellationToken, true);
}
finally
{
ServerStatusChangeCallback?.Invoke(ServerStatus.Stopped);
}
}
if (ExitCode != EXITCODE_NORMALEXIT)
@ -3060,7 +3070,7 @@ namespace ServerManagerTool.Lib
if (exitCode == EXITCODE_NORMALEXIT)
{
var branches = _profiles.Keys.Where(p => p.EnableAutoUpdate).Select(p => new BranchSnapshot() { BranchName = p.BranchName, BranchPassword = p.BranchPassword }).Distinct(new BranchSnapshotComparer()).ToArray();
var branches = _profiles.Keys.Where(p => p.EnableAutoUpdate).Select(p => BranchSnapshot.Create(p)).Distinct(new BranchSnapshotComparer()).ToArray();
var exitCodes = new ConcurrentDictionary<BranchSnapshot, int>();
// update the server cache for each branch

View file

@ -7,6 +7,10 @@ namespace ServerManagerTool.Lib
{
public class ServerProfileSnapshot
{
private ServerProfileSnapshot()
{
}
public string ProfileId;
public string ProfileName;
public string ServerName;

View file

@ -32,7 +32,7 @@ namespace ServerManagerTool.Lib
public event EventHandler StatusUpdate;
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
private static readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
private readonly List<PropertyChangeNotifier> profileNotifiers = new List<PropertyChangeNotifier>();
private Process serverProcess;
private IAsyncDisposable updateRegistration;
@ -442,7 +442,7 @@ namespace ServerManagerTool.Lib
}
}
UpdateServerStatus(ServerStatus.Initializing, this.Availability, false);
UpdateServerStatus(ServerStatus.Initializing, false);
try
{
@ -516,7 +516,7 @@ namespace ServerManagerTool.Lib
bool isNewInstallation = this.Status == ServerStatus.Uninstalled;
UpdateServerStatus(ServerStatus.Updating, Availability, false);
UpdateServerStatus(ServerStatus.Updating, false);
// Run the SteamCMD to install the server
var steamCmdFile = SteamCmdUpdater.GetSteamCmdFile(Config.Default.DataPath);
@ -938,7 +938,7 @@ namespace ServerManagerTool.Lib
finally
{
this.lastModStatusQuery = DateTime.MinValue;
UpdateServerStatus(ServerStatus.Stopped, Availability, false);
UpdateServerStatus(ServerStatus.Stopped, false);
}
}
@ -961,6 +961,11 @@ namespace ServerManagerTool.Lib
this.lastModStatusQuery = DateTime.MinValue;
}
public void UpdateServerStatus(ServerStatus serverStatus, bool sendAlert)
{
UpdateServerStatus(serverStatus, Availability, sendAlert);
}
public void UpdateServerStatus(ServerStatus serverStatus, AvailabilityStatus availabilityStatus, bool sendAlert)
{
this.Status = serverStatus;
@ -974,32 +979,29 @@ namespace ServerManagerTool.Lib
public void UpdateServerStatusString()
{
switch (Status)
StatusString = GetServerStatusString(Status);
}
public static string GetServerStatusString(ServerStatus status)
{
switch (status)
{
case ServerStatus.Initializing:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusInitializingLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusInitializingLabel");
case ServerStatus.Running:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusRunningLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusRunningLabel");
case ServerStatus.Stopped:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusStoppedLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusStoppedLabel");
case ServerStatus.Stopping:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusStoppingLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusStoppingLabel");
case ServerStatus.Uninstalled:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusUninstalledLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusUninstalledLabel");
case ServerStatus.Unknown:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusUnknownLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusUnknownLabel");
case ServerStatus.Updating:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusUpdatingLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusUpdatingLabel");
default:
StatusString = _globalizer.GetResourceString("ServerSettings_RuntimeStatusUnknownLabel");
break;
return _globalizer.GetResourceString("ServerSettings_RuntimeStatusUnknownLabel");
}
}

View file

@ -1,11 +1,15 @@
using QueryMaster;
using ServerManagerTool.Common.Utils;
using ServerManagerTool.DiscordBot.Enums;
using ServerManagerTool.Enums;
using ServerManagerTool.Lib;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using WPFSharp.Globalizer;
namespace ServerManagerTool.Utils
@ -15,6 +19,10 @@ namespace ServerManagerTool.Utils
private static readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
private static bool _runningCommand = false;
private static readonly Dictionary<string, CommandType> _currentProfileCommands = new Dictionary<string, CommandType>();
public static bool HasRunningCommands => _currentProfileCommands.Count > 0;
public static IList<string> HandleDiscordCommand(CommandType commandType, string serverId, string channelId, string profileId)
{
// check if incoming values are valid
@ -57,7 +65,8 @@ namespace ServerManagerTool.Utils
}
catch (Exception ex)
{
return new string[] { ex.Message };
var message = ex.InnerException is null ? ex.Message : ex.InnerException.Message;
return new string[] { message };
}
finally
{
@ -74,54 +83,68 @@ namespace ServerManagerTool.Utils
{
if (string.IsNullOrWhiteSpace(profileId))
{
return new List<string> { _globalizer.GetResourceString("DiscordBot_CommandProfileMissing") };
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Info) };
}
var serverName = string.Empty;
var serverIp = IPAddress.Loopback;
var queryPort = 0;
TaskUtils.RunOnUIThreadAsync(() =>
// check if another command is being run against the profile
if (_currentProfileCommands.ContainsKey(profileId))
{
var server = ServerManager.Instance.Servers.Where(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID)).FirstOrDefault();
if (server is null)
{
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandProfileNotFound"), profileId));
}
serverName = server.Profile.ServerName;
if (!string.IsNullOrWhiteSpace(server.Profile.ServerIP))
{
IPAddress.TryParse(server.Profile.ServerIP, out serverIp);
}
queryPort = server.Profile.QueryPort;
}).Wait();
List<string> response = new List<string>();
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
}
_currentProfileCommands.Add(profileId, CommandType.Info);
try
{
using (var gameServer = ServerQuery.GetServerInstance(EngineType.Source, new IPEndPoint(serverIp, queryPort)))
var serverName = string.Empty;
var serverIp = IPAddress.Loopback;
var queryPort = 0;
TaskUtils.RunOnUIThreadAsync(() =>
{
var info = gameServer?.GetInfo();
if (info is null)
var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
if (server is null)
{
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_CommandInfoFailed"), serverName));
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
}
else
serverName = server.Profile.ServerName;
if (!string.IsNullOrWhiteSpace(server.Profile.ServerIP))
{
var mapName = _globalizer.GetResourceString($"Map_{info.Map}") ?? info.Map;
response.Add($"```{info.Name}\n{_globalizer.GetResourceString("DiscordBot_MapLabel")} {mapName}\n{_globalizer.GetResourceString("ServerSettings_PlayersLabel")} {info.Players} / {info.MaxPlayers}```");
IPAddress.TryParse(server.Profile.ServerIP, out serverIp);
}
queryPort = server.Profile.QueryPort;
}).Wait();
List<string> response = new List<string>();
try
{
using (var gameServer = ServerQuery.GetServerInstance(EngineType.Source, new IPEndPoint(serverIp, queryPort)))
{
var info = gameServer?.GetInfo();
if (info is null)
{
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_InfoFailed"), serverName));
}
else
{
var mapName = _globalizer.GetResourceString($"Map_{info.Map}") ?? info.Map;
response.Add($"```{info.Name}\n{_globalizer.GetResourceString("DiscordBot_MapLabel")} {mapName}\n{_globalizer.GetResourceString("ServerSettings_PlayersLabel")} {info.Players} / {info.MaxPlayers}```");
}
}
}
}
catch (Exception)
{
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_CommandInfoFailed"), serverName));
}
catch (Exception)
{
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_InfoFailed"), serverName));
}
return response;
return response;
}
finally
{
_currentProfileCommands.Remove(profileId);
}
}
private static IList<string> GetServerList(string channelId)
@ -162,7 +185,63 @@ namespace ServerManagerTool.Utils
private static IList<string> BackupServer(string channelId, string profileId)
{
return new List<string>() { string.Format(_globalizer.GetResourceString("DiscordBot_CommandUnknown"), CommandType.Backup) };
if (string.IsNullOrWhiteSpace(profileId))
{
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Backup) };
}
// check if another command is being run against the profile
if (_currentProfileCommands.ContainsKey(profileId))
{
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
}
_currentProfileCommands.Add(profileId, CommandType.Backup);
ServerProfileSnapshot profile = null;
Task task = null;
try
{
TaskUtils.RunOnUIThreadAsync(() =>
{
var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
if (server is null)
{
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
}
profile = ServerProfileSnapshot.Create(server.Profile);
}).Wait();
List<string> response = new List<string>();
var app = new ServerApp(true)
{
DeleteOldServerBackupFiles = !Config.Default.AutoBackup_EnableBackup,
OutputLogs = false,
SendAlerts = true,
SendEmails = false,
ServerProcess = ServerProcessType.Backup,
};
task = Task.Run(() =>
{
app.PerformProfileBackup(profile);
_currentProfileCommands.Remove(profileId);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_BackupRequested"), profile.ServerName));
return response;
}
finally
{
if (task is null)
{
_currentProfileCommands.Remove(profileId);
}
}
}
private static IList<string> ShutdownServer(string channelId, string profileId)
@ -182,7 +261,87 @@ namespace ServerManagerTool.Utils
private static IList<string> UpdateServer(string channelId, string profileId)
{
return new List<string>() { string.Format(_globalizer.GetResourceString("DiscordBot_CommandUnknown"), CommandType.Update) };
if (string.IsNullOrWhiteSpace(profileId))
{
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Update) };
}
// check if another command is being run against the profile
if (_currentProfileCommands.ContainsKey(profileId))
{
return new List<string> { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
}
_currentProfileCommands.Add(profileId, CommandType.Update);
ServerProfileSnapshot profile = null;
bool performRestart = false;
Task task = null;
try
{
TaskUtils.RunOnUIThreadAsync(() =>
{
var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
if (server is null)
{
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
}
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
case ServerStatus.Stopping:
case ServerStatus.Unknown:
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, ServerRuntime.GetServerStatusString(ServerStatus.Stopped)));
case ServerStatus.Running:
performRestart = true;
break;
case ServerStatus.Updating:
throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
}
profile = ServerProfileSnapshot.Create(server.Profile);
}).Wait();
List<string> response = new List<string>();
var app = new ServerApp(true)
{
DeleteOldServerBackupFiles = !Config.Default.AutoBackup_EnableBackup,
OutputLogs = false,
SendAlerts = true,
SendEmails = false,
ServerProcess = ServerProcessType.Update,
ServerStatusChangeCallback = (ServerStatus serverStatus) =>
{
TaskUtils.RunOnUIThreadAsync(() =>
{
var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
};
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, performRestart, true, false, false, CancellationToken.None);
_currentProfileCommands.Remove(profileId);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_UpdateRequested"), profile.ServerName));
return response;
}
finally
{
if (task is null)
{
_currentProfileCommands.Remove(profileId);
}
}
}
}
}

View file

@ -10,7 +10,7 @@
xmlns:com="clr-namespace:ServerManagerTool.Common;assembly=ServerManager.Common"
xmlns:enum="clr-namespace:ServerManagerTool.Enums"
MinWidth="900" MinHeight="600" Width="1100" Height="900" Left="50" Top="50" WindowState="Normal"
Loaded="Window_Loaded" SizeChanged="Window_SizeChanged" StateChanged="Window_StateChanged" LocationChanged="Window_LocationChanged"
Loaded="MainWindow_Loaded" SizeChanged="MainWindow_SizeChanged" StateChanged="MainWindow_StateChanged" LocationChanged="MainWindow_LocationChanged"
Name="Main" Icon="../Art/favicon.ico" Title="{DynamicResource MainWindow_Title}">
<Window.Resources>
<ResourceDictionary>

View file

@ -6,6 +6,7 @@ using ServerManagerTool.Common.Utils;
using ServerManagerTool.Enums;
using ServerManagerTool.Lib;
using ServerManagerTool.Plugin.Common;
using ServerManagerTool.Utils;
using ServerManagerTool.Windows;
using System;
using System.Diagnostics;
@ -162,7 +163,7 @@ namespace ServerManagerTool
GlobalizedApplication.Instance.GlobalizationManager.ResourceDictionaryChangedEvent += ResourceDictionaryChangedEvent;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
//
// Kick off the initialization.
@ -192,15 +193,7 @@ namespace ServerManagerTool
this.scheduledTaskChecker.PostAction(CheckForScheduledTasks).DoNotWait();
}
private void Window_Closed(object sender, EventArgs e)
{
if (sender is Window window)
window.Closed -= Window_Closed;
this.Activate();
}
private void Window_LocationChanged(object sender, EventArgs e)
private void MainWindow_LocationChanged(object sender, EventArgs e)
{
if (this.WindowState == WindowState.Normal)
{
@ -209,7 +202,7 @@ namespace ServerManagerTool
}
}
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (this.WindowState == WindowState.Normal)
{
@ -218,7 +211,7 @@ namespace ServerManagerTool
}
}
private void Window_StateChanged(object sender, EventArgs e)
private void MainWindow_StateChanged(object sender, EventArgs e)
{
if (Config.Default.MainWindow_MinimizeToTray && this.WindowState == WindowState.Minimized)
{
@ -226,8 +219,26 @@ namespace ServerManagerTool
}
}
private void Window_Closed(object sender, EventArgs e)
{
if (sender is Window window)
window.Closed -= Window_Closed;
this.Activate();
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if (DiscordBotHelper.HasRunningCommands)
{
var result = MessageBox.Show(_globalizer.GetResourceString("MainWindow_DiscordBot_RunningCommandsLabel"), _globalizer.GetResourceString("MainWindow_DiscordBot_RunningCommandsTitle"), MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.No)
{
e.Cancel = true;
return;
}
}
base.OnClosing(e);
RconWindow.CloseAllWindows();
PlayerListWindow.CloseAllWindows();

View file

@ -620,7 +620,7 @@ namespace ServerManagerTool.Windows
await Task.Delay(1000);
var branch = new BranchSnapshot() { BranchName = serverProfile.BranchName, BranchPassword = serverProfile.BranchPassword };
var branch = BranchSnapshot.Create(serverProfile);
return await server.UpgradeAsync(_upgradeCancellationSource.Token, updateServer, branch, true, updateMods, (p, m, n) => { TaskUtils.RunOnUIThreadAsync(() => { window?.AddMessage(m, n); }).DoNotWait(); });
}
else

View file

@ -1449,7 +1449,7 @@ namespace ServerManagerTool
await Task.Delay(1000);
var branch = new BranchSnapshot() { BranchName = this.Server.Profile.BranchName, BranchPassword = this.Server.Profile.BranchPassword };
var branch = BranchSnapshot.Create(this.Server.Profile);
return await this.Server.UpgradeAsync(_upgradeCancellationSource.Token, updateServer, branch, true, updateMods, (p, m, n) => { TaskUtils.RunOnUIThreadAsync(() => { window?.AddMessage(m, n); }).DoNotWait(); });
}
else

View file

@ -23,15 +23,6 @@ namespace ServerManagerTool.DiscordBot.Modules
_config = config;
}
[Command("backup", RunMode = RunMode.Async)]
[Summary("Perform a backup of the server")]
[Remarks("backup")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
public async Task BackupServerAsync()
{
await BackupServerAsync(null);
}
[Command("backup", RunMode = RunMode.Async)]
[Summary("Perform a backup of the server")]
[Remarks("backup profileId")]
@ -63,15 +54,6 @@ namespace ServerManagerTool.DiscordBot.Modules
}
}
[Command("shutdown", RunMode = RunMode.Async)]
[Summary("Shuts down the server properly")]
[Remarks("shutdown")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
public async Task ShutdownServerAsync()
{
await ShutdownServerAsync(null);
}
[Command("shutdown", RunMode = RunMode.Async)]
[Summary("Shuts down the server properly")]
[Remarks("shutdown profileId")]
@ -103,15 +85,6 @@ namespace ServerManagerTool.DiscordBot.Modules
}
}
[Command("start", RunMode = RunMode.Async)]
[Summary("Starts the server")]
[Remarks("start")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
public async Task StartServerAsync()
{
await StartServerAsync(null);
}
[Command("start", RunMode = RunMode.Async)]
[Summary("Starts the server")]
[Remarks("start profileId")]
@ -143,15 +116,6 @@ namespace ServerManagerTool.DiscordBot.Modules
}
}
[Command("stop", RunMode = RunMode.Async)]
[Summary("Forcibly stops the server")]
[Remarks("stop")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
public async Task StopServerAsync()
{
await StopServerAsync(null);
}
[Command("stop", RunMode = RunMode.Async)]
[Summary("Forcibly stops the server")]
[Remarks("stop profileId")]
@ -183,15 +147,6 @@ namespace ServerManagerTool.DiscordBot.Modules
}
}
[Command("update", RunMode = RunMode.Async)]
[Summary("Updates the server")]
[Remarks("update")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
public async Task UpdateServerAsync()
{
await UpdateServerAsync(null);
}
[Command("update", RunMode = RunMode.Async)]
[Summary("Updates the server")]
[Remarks("update profileId")]