mirror of
https://github.com/tribufu/ServerManagers
synced 2026-05-06 15:17:34 +00:00
1511 lines
No EOL
68 KiB
C#
1511 lines
No EOL
68 KiB
C#
using Microsoft.WindowsAPICodePack.Dialogs;
|
|
using ServerManagerTool.Common;
|
|
using ServerManagerTool.Common.Lib;
|
|
using ServerManagerTool.Common.Model;
|
|
using ServerManagerTool.Common.Utils;
|
|
using ServerManagerTool.Enums;
|
|
using ServerManagerTool.Lib;
|
|
using ServerManagerTool.Plugin.Common;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Controls.Primitives;
|
|
using System.Windows.Data;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Input;
|
|
using WPFSharp.Globalizer;
|
|
|
|
namespace ServerManagerTool
|
|
{
|
|
partial class ServerSettingsControl : UserControl
|
|
{
|
|
private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
|
|
private CancellationTokenSource _upgradeCancellationSource = null;
|
|
|
|
// Using a DependencyProperty as the backing store for ServerManager. This enables animation, styling, binding, etc...
|
|
public static readonly DependencyProperty BaseGameMapsProperty = DependencyProperty.Register(nameof(BaseGameMaps), typeof(ComboBoxItemList), typeof(ServerSettingsControl), new PropertyMetadata(null));
|
|
public static readonly DependencyProperty BaseBranchesProperty = DependencyProperty.Register(nameof(BaseBranches), typeof(ComboBoxItemList), typeof(ServerSettingsControl), new PropertyMetadata(null));
|
|
public static readonly DependencyProperty ConfigProperty = DependencyProperty.Register(nameof(Config), typeof(Config), typeof(ServerSettingsControl));
|
|
public static readonly DependencyProperty IsAdministratorProperty = DependencyProperty.Register(nameof(IsAdministrator), typeof(bool), typeof(ServerSettingsControl), new PropertyMetadata(false));
|
|
public static readonly DependencyProperty NetworkInterfacesProperty = DependencyProperty.Register(nameof(NetworkInterfaces), typeof(List<NetworkAdapterEntry>), typeof(ServerSettingsControl), new PropertyMetadata(new List<NetworkAdapterEntry>()));
|
|
public static readonly DependencyProperty RuntimeProperty = DependencyProperty.Register(nameof(Runtime), typeof(ServerRuntime), typeof(ServerSettingsControl));
|
|
public static readonly DependencyProperty ServerManagerProperty = DependencyProperty.Register(nameof(ServerManager), typeof(ServerManager), typeof(ServerSettingsControl), new PropertyMetadata(null));
|
|
public static readonly DependencyProperty ServerProperty = DependencyProperty.Register(nameof(Server), typeof(Server), typeof(ServerSettingsControl), new PropertyMetadata(null, ServerPropertyChanged));
|
|
public static readonly DependencyProperty SettingsProperty = DependencyProperty.Register(nameof(Settings), typeof(ServerProfile), typeof(ServerSettingsControl));
|
|
public static readonly DependencyProperty ProcessPrioritiesProperty = DependencyProperty.Register(nameof(ProcessPriorities), typeof(ComboBoxItemList), typeof(ServerSettingsControl), new PropertyMetadata(null));
|
|
public static readonly DependencyProperty ServerRegionsProperty = DependencyProperty.Register(nameof(ServerRegions), typeof(ComboBoxItemList), typeof(ServerSettingsControl), new PropertyMetadata(null));
|
|
public static readonly DependencyProperty CurrentCultureProperty = DependencyProperty.Register(nameof(CurrentCulture), typeof(CultureInfo), typeof(ServerSettingsControl), new PropertyMetadata(null));
|
|
public static readonly DependencyProperty DisplayModInformationProperty = DependencyProperty.Register(nameof(DisplayModInformation), typeof(bool), typeof(ServerSettingsControl), new PropertyMetadata(false));
|
|
public static readonly DependencyProperty ProfileLastStartedProperty = DependencyProperty.Register(nameof(ProfileLastStarted), typeof(string), typeof(ServerSettingsControl), new PropertyMetadata(""));
|
|
|
|
#region Properties
|
|
public ComboBoxItemList BaseGameMaps
|
|
{
|
|
get { return (ComboBoxItemList)GetValue(BaseGameMapsProperty); }
|
|
set { SetValue(BaseGameMapsProperty, value); }
|
|
}
|
|
|
|
public ComboBoxItemList BaseBranches
|
|
{
|
|
get { return (ComboBoxItemList)GetValue(BaseBranchesProperty); }
|
|
set { SetValue(BaseBranchesProperty, value); }
|
|
}
|
|
|
|
public Config Config
|
|
{
|
|
get { return GetValue(ConfigProperty) as Config; }
|
|
set { SetValue(ConfigProperty, value); }
|
|
}
|
|
|
|
public bool IsAdministrator
|
|
{
|
|
get { return (bool)GetValue(IsAdministratorProperty); }
|
|
set { SetValue(IsAdministratorProperty, value); }
|
|
}
|
|
|
|
public List<NetworkAdapterEntry> NetworkInterfaces
|
|
{
|
|
get { return (List<NetworkAdapterEntry>)GetValue(NetworkInterfacesProperty); }
|
|
set { SetValue(NetworkInterfacesProperty, value); }
|
|
}
|
|
|
|
public ServerRuntime Runtime
|
|
{
|
|
get { return GetValue(RuntimeProperty) as ServerRuntime; }
|
|
set { SetValue(RuntimeProperty, value); }
|
|
}
|
|
|
|
public ServerManager ServerManager
|
|
{
|
|
get { return (ServerManager)GetValue(ServerManagerProperty); }
|
|
set { SetValue(ServerManagerProperty, value); }
|
|
}
|
|
|
|
public Server Server
|
|
{
|
|
get { return (Server)GetValue(ServerProperty); }
|
|
set { SetValue(ServerProperty, value); }
|
|
}
|
|
|
|
public ServerProfile Settings
|
|
{
|
|
get { return GetValue(SettingsProperty) as ServerProfile; }
|
|
set { SetValue(SettingsProperty, value); }
|
|
}
|
|
|
|
public ComboBoxItemList ProcessPriorities
|
|
{
|
|
get { return (ComboBoxItemList)GetValue(ProcessPrioritiesProperty); }
|
|
set { SetValue(ProcessPrioritiesProperty, value); }
|
|
}
|
|
|
|
public ComboBoxItemList ServerRegions
|
|
{
|
|
get { return (ComboBoxItemList)GetValue(ServerRegionsProperty); }
|
|
set { SetValue(ServerRegionsProperty, value); }
|
|
}
|
|
|
|
public CultureInfo CurrentCulture
|
|
{
|
|
get { return (CultureInfo)GetValue(CurrentCultureProperty); }
|
|
set { SetValue(CurrentCultureProperty, value); }
|
|
}
|
|
|
|
public bool DisplayModInformation
|
|
{
|
|
get { return (bool)GetValue(DisplayModInformationProperty); }
|
|
set { SetValue(DisplayModInformationProperty, value); }
|
|
}
|
|
|
|
public string ProfileLastStarted
|
|
{
|
|
get { return (string)GetValue(ProfileLastStartedProperty); }
|
|
set { SetValue(ProfileLastStartedProperty, value); }
|
|
}
|
|
#endregion
|
|
|
|
public ServerSettingsControl()
|
|
{
|
|
this.Config = Config.Default;
|
|
this.CurrentCulture = Thread.CurrentThread.CurrentCulture;
|
|
|
|
InitializeComponent();
|
|
WindowUtils.RemoveDefaultResourceDictionary(this, Config.Default.DefaultGlobalizationFile);
|
|
|
|
this.ServerManager = ServerManager.Instance;
|
|
this.IsAdministrator = SecurityUtils.IsAdministrator();
|
|
this.DisplayModInformation = !string.IsNullOrWhiteSpace(SteamUtils.SteamWebApiKey);
|
|
|
|
this.BaseGameMaps = new ComboBoxItemList();
|
|
this.BaseBranches = new ComboBoxItemList();
|
|
this.ProcessPriorities = new ComboBoxItemList();
|
|
this.ServerRegions = new ComboBoxItemList();
|
|
|
|
UpdateLastStartedDetails(false);
|
|
|
|
// hook into the language change event
|
|
GlobalizedApplication.Instance.GlobalizationManager.ResourceDictionaryChangedEvent += ResourceDictionaryChangedEvent;
|
|
}
|
|
|
|
#region Event Methods
|
|
private static void ServerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
var ssc = (ServerSettingsControl)d;
|
|
var oldserver = (Server)e.OldValue;
|
|
var server = (Server)e.NewValue;
|
|
if (server != null)
|
|
{
|
|
TaskUtils.RunOnUIThreadAsync(() =>
|
|
{
|
|
oldserver?.Profile.Save(false, false, null);
|
|
|
|
ssc.Settings = server.Profile;
|
|
ssc.Runtime = server.Runtime;
|
|
ssc.ReinitializeNetworkAdapters();
|
|
ssc.RefreshBaseGameMapsList();
|
|
ssc.RefreshBaseBranchesList();
|
|
ssc.RefreshProcessPrioritiesList();
|
|
ssc.RefreshServerRegionsList();
|
|
ssc.DisplayModInformation = !string.IsNullOrWhiteSpace(SteamUtils.SteamWebApiKey);
|
|
ssc.UpdateLastStartedDetails(false);
|
|
}).DoNotWait();
|
|
}
|
|
}
|
|
|
|
private void ResourceDictionaryChangedEvent(object source, ResourceDictionaryChangedEventArgs e)
|
|
{
|
|
this.CurrentCulture = Thread.CurrentThread.CurrentCulture;
|
|
|
|
this.RefreshBaseGameMapsList();
|
|
this.RefreshBaseBranchesList();
|
|
this.RefreshProcessPrioritiesList();
|
|
this.RefreshServerRegionsList();
|
|
this.UpdateLastStartedDetails(false);
|
|
|
|
Runtime.UpdateServerStatusString();
|
|
}
|
|
|
|
private void Window_Closed(object sender, EventArgs e)
|
|
{
|
|
Window.GetWindow(this)?.Activate();
|
|
|
|
if (sender is Window)
|
|
((Window)sender).Closed -= Window_Closed;
|
|
|
|
if (sender is ShutdownWindow)
|
|
this.Runtime?.ResetModCheckTimer();
|
|
|
|
if (sender is ModDetailsWindow)
|
|
{
|
|
((ModDetailsWindow)sender).SavePerformed -= ModDetailsWindow_SavePerformed;
|
|
RefreshBaseGameMapsList();
|
|
}
|
|
}
|
|
|
|
private void ModDetailsWindow_SavePerformed(object sender, ProfileEventArgs e)
|
|
{
|
|
if (sender is ModDetailsWindow && Equals(e.Profile, Settings))
|
|
{
|
|
RefreshBaseGameMapsList();
|
|
}
|
|
}
|
|
|
|
private async void Start_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
MessageBoxResult result = MessageBoxResult.None;
|
|
|
|
switch (this.Runtime.Status)
|
|
{
|
|
case ServerStatus.Initializing:
|
|
case ServerStatus.Running:
|
|
// check if the server is initialising.
|
|
if (this.Runtime.Status == ServerStatus.Initializing)
|
|
{
|
|
result = MessageBox.Show(_globalizer.GetResourceString("ServerSettings_StartServer_StartingLabel"), _globalizer.GetResourceString("ServerSettings_StartServer_StartingTitle"), MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
|
if (result == MessageBoxResult.No)
|
|
return;
|
|
|
|
try
|
|
{
|
|
PluginHelper.Instance.ProcessAlert(AlertType.Shutdown, this.Settings.ProfileName, Config.Default.Alert_ServerStopMessage);
|
|
await Task.Delay(2000);
|
|
|
|
await this.Server.StopAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_StopServer_FailedTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
var shutdownWindow = ShutdownWindow.OpenShutdownWindow(this.Server);
|
|
if (shutdownWindow == null)
|
|
{
|
|
MessageBox.Show(_globalizer.GetResourceString("ServerSettings_ShutdownServer_AlreadyOpenLabel"), _globalizer.GetResourceString("ServerSettings_ShutdownServer_FailedTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
|
return;
|
|
}
|
|
|
|
shutdownWindow.Owner = Window.GetWindow(this);
|
|
shutdownWindow.Closed += Window_Closed;
|
|
shutdownWindow.Show();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_ShutdownServer_FailedTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ServerStatus.Stopped:
|
|
Mutex mutex = null;
|
|
bool createdNew = false;
|
|
|
|
try
|
|
{
|
|
// try to establish a mutex for the profile.
|
|
mutex = new Mutex(true, ServerApp.GetMutexName(this.Server.Profile.InstallDirectory), out createdNew);
|
|
|
|
// check if the mutex was established
|
|
if (createdNew)
|
|
{
|
|
if (Config.Default.ManagePublicIPAutomatically)
|
|
{
|
|
// check and update the public IP address
|
|
await App.DiscoverMachinePublicIPAsync(false);
|
|
}
|
|
|
|
this.Settings.Save(false, false, null);
|
|
|
|
if (Config.Default.ServerUpdate_OnServerStart)
|
|
{
|
|
if (!await UpdateServer(false, true, Config.Default.ServerUpdate_UpdateModsWhenUpdatingServer, true))
|
|
{
|
|
if (MessageBox.Show(_globalizer.GetResourceString("ServerUpdate_WarningLabel"), _globalizer.GetResourceString("ServerUpdate_Title"), MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes)
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!this.Server.Profile.Validate(false, out string validateMessage))
|
|
{
|
|
var outputMessage = _globalizer.GetResourceString("ProfileValidation_WarningLabel").Replace("{validateMessage}", validateMessage);
|
|
if (MessageBox.Show(outputMessage, _globalizer.GetResourceString("ProfileValidation_Title"), MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes)
|
|
return;
|
|
}
|
|
|
|
await this.Server.StartAsync();
|
|
|
|
// update the profile's last started time
|
|
UpdateLastStartedDetails(true);
|
|
|
|
var startupMessage = Config.Default.Alert_ServerStartedMessage;
|
|
if (Config.Default.Alert_ServerStartedMessageIncludeIPandPort)
|
|
startupMessage += $" {Config.Default.MachinePublicIP}:{this.Settings.QueryPort}";
|
|
PluginHelper.Instance.ProcessAlert(AlertType.Startup, this.Settings.ProfileName, startupMessage);
|
|
|
|
await Task.Delay(2000);
|
|
}
|
|
else
|
|
{
|
|
// display an error message and exit
|
|
MessageBox.Show(_globalizer.GetResourceString("ServerSettings_StartServer_MutexFailedLabel"), _globalizer.GetResourceString("ServerSettings_StartServer_FailedTitle"), MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_StartServer_FailedTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
finally
|
|
{
|
|
if (mutex != null)
|
|
{
|
|
if (createdNew)
|
|
{
|
|
mutex.ReleaseMutex();
|
|
mutex.Dispose();
|
|
}
|
|
mutex = null;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
private async void Upgrade_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
switch (this.Runtime.Status)
|
|
{
|
|
case ServerStatus.Stopped:
|
|
case ServerStatus.Uninstalled:
|
|
break;
|
|
|
|
case ServerStatus.Running:
|
|
case ServerStatus.Initializing:
|
|
var result = MessageBox.Show(_globalizer.GetResourceString("ServerSettings_UpgradeServer_RunningLabel"), _globalizer.GetResourceString("ServerSettings_UpgradeServer_RunningTitle"), MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
|
if (result == MessageBoxResult.No)
|
|
return;
|
|
|
|
break;
|
|
|
|
case ServerStatus.Updating:
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
this.Settings.Save(false, false, null);
|
|
await UpdateServer(true, true, Config.Default.ServerUpdate_UpdateModsWhenUpdatingServer, false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_UpdateServer_FailedTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
}
|
|
|
|
private async void ModUpgrade_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
switch (this.Runtime.Status)
|
|
{
|
|
case ServerStatus.Stopped:
|
|
case ServerStatus.Uninstalled:
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
this.Settings.Save(false, false, null);
|
|
await UpdateServer(true, false, true, false);
|
|
}
|
|
|
|
private void OpenRcon_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var window = RconWindow.GetRconForServer(this.Server);
|
|
window.Closed += Window_Closed;
|
|
window.Show();
|
|
if (window.WindowState == WindowState.Minimized)
|
|
{
|
|
window.WindowState = WindowState.Normal;
|
|
}
|
|
|
|
window.Focus();
|
|
}
|
|
|
|
private void OpenPlayerList_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var window = PlayerListWindow.GetWindowForServer(this.Server);
|
|
window.Closed += Window_Closed;
|
|
window.Show();
|
|
if (window.WindowState == WindowState.Minimized)
|
|
{
|
|
window.WindowState = WindowState.Normal;
|
|
}
|
|
|
|
window.Focus();
|
|
}
|
|
|
|
private void OpenModDetails_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var window = new ModDetailsWindow(this.Server.Profile)
|
|
{
|
|
Owner = Window.GetWindow(this)
|
|
};
|
|
window.Closed += Window_Closed;
|
|
window.SavePerformed += ModDetailsWindow_SavePerformed;
|
|
window.Show();
|
|
window.Focus();
|
|
}
|
|
|
|
private void PatchNotes_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(Config.Default.AppPatchNotesUrl))
|
|
return;
|
|
|
|
Process.Start(Config.Default.AppPatchNotesUrl);
|
|
}
|
|
|
|
private void NeedAdmin_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
MessageBox.Show(_globalizer.GetResourceString("ServerSettings_AdminRequired_ErrorLabel"), _globalizer.GetResourceString("ServerSettings_AdminRequired_ErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
|
|
private void RefreshLocalIPs_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
ReinitializeNetworkAdapters();
|
|
}
|
|
|
|
private void OpenLogFolder_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var logFolder = Path.Combine(App.GetLogFolder(), this.Server.Profile.ProfileID.ToLower());
|
|
if (!Directory.Exists(logFolder))
|
|
logFolder = App.GetLogFolder();
|
|
if (!Directory.Exists(logFolder))
|
|
logFolder = Config.Default.DataPath;
|
|
Process.Start("explorer.exe", logFolder);
|
|
}
|
|
|
|
private void OpenServerFolder_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
Process.Start("explorer.exe", this.Server.Profile.InstallDirectory);
|
|
}
|
|
|
|
private async void CreateSupportZip_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
const int MAX_DAYS = 2;
|
|
|
|
var cursor = this.Cursor;
|
|
|
|
try
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() => this.Cursor = Cursors.Wait);
|
|
await Task.Delay(500);
|
|
|
|
var obfuscateFiles = new Dictionary<string, string>();
|
|
var files = new List<string>();
|
|
|
|
// <server>
|
|
var file = Path.Combine(this.Settings.InstallDirectory, Config.Default.LastUpdatedTimeFile);
|
|
if (File.Exists(file)) files.Add(file);
|
|
|
|
// <server>\ConanSandbox\mods
|
|
var folder = Path.Combine(this.Settings.InstallDirectory, Config.Default.ServerModsRelativePath);
|
|
var dirInfo = new DirectoryInfo(folder);
|
|
if (dirInfo.Exists)
|
|
{
|
|
files.AddRange(dirInfo.GetFiles("*.txt").Select(timeFile => timeFile.FullName));
|
|
|
|
var modListFile = Path.Combine(folder, Config.Default.ServerModListFile);
|
|
if (File.Exists(modListFile) && !files.Contains(modListFile))
|
|
files.Add(modListFile);
|
|
}
|
|
|
|
// <server>\ConanSandbox\Saved\Config\WindowsServer
|
|
file = Path.Combine(this.Settings.GetProfileServerConfigDir(), Config.Default.ServerEngineConfigFile);
|
|
if (File.Exists(file))
|
|
{
|
|
var iniFile = IniFileUtils.ReadFromFile(file);
|
|
if (iniFile != null)
|
|
{
|
|
iniFile.WriteKey("OnlineSubsystem", "ServerPassword", "obfuscated");
|
|
iniFile.WriteKey("OnlineSubsystemSteam", "ServerPassword", "obfuscated");
|
|
obfuscateFiles.Add(file, iniFile.ToOutputString());
|
|
}
|
|
}
|
|
file = Path.Combine(this.Settings.GetProfileServerConfigDir(), Config.Default.ServerGameConfigFile);
|
|
if (File.Exists(file))
|
|
{
|
|
var iniFile = IniFileUtils.ReadFromFile(file);
|
|
if (iniFile != null)
|
|
{
|
|
obfuscateFiles.Add(file, iniFile.ToOutputString());
|
|
}
|
|
}
|
|
file = Path.Combine(this.Settings.GetProfileServerConfigDir(), Config.Default.ServerSettingsConfigFile);
|
|
if (File.Exists(file))
|
|
{
|
|
var iniFile = IniFileUtils.ReadFromFile(file);
|
|
if (iniFile != null)
|
|
{
|
|
iniFile.WriteKey("ServerSettings", "AdminPassword", "obfuscated");
|
|
obfuscateFiles.Add(file, iniFile.ToOutputString());
|
|
}
|
|
}
|
|
file = Path.Combine(this.Settings.GetProfileServerConfigDir(), Config.Default.LauncherFile);
|
|
if (File.Exists(file)) files.Add(file);
|
|
|
|
// Logs
|
|
folder = Path.Combine(Config.Default.DataPath, Config.Default.LogsRelativePath);
|
|
dirInfo = new DirectoryInfo(folder);
|
|
if (dirInfo.Exists)
|
|
{
|
|
files.AddRange(dirInfo.GetFiles("*.log").Where(f => f.LastWriteTime > DateTime.Today.AddDays(-MAX_DAYS)).Select(logFile => logFile.FullName));
|
|
}
|
|
|
|
folder = Path.Combine(Config.Default.DataPath, Config.Default.LogsRelativePath, ServerApp.LOGPREFIX_AUTOBACKUP);
|
|
dirInfo = new DirectoryInfo(folder);
|
|
if (dirInfo.Exists)
|
|
{
|
|
files.AddRange(dirInfo.GetFiles("*.log").Where(f => f.LastWriteTime > DateTime.Today.AddDays(-MAX_DAYS)).Select(logFile => logFile.FullName));
|
|
}
|
|
|
|
folder = Path.Combine(Config.Default.DataPath, Config.Default.LogsRelativePath, ServerApp.LOGPREFIX_AUTOSHUTDOWN);
|
|
dirInfo = new DirectoryInfo(folder);
|
|
if (dirInfo.Exists)
|
|
{
|
|
files.AddRange(dirInfo.GetFiles("*.log").Where(f => f.LastWriteTime > DateTime.Today.AddDays(-MAX_DAYS)).Select(logFile => logFile.FullName));
|
|
}
|
|
|
|
folder = Path.Combine(Config.Default.DataPath, Config.Default.LogsRelativePath, ServerApp.LOGPREFIX_AUTOUPDATE);
|
|
dirInfo = new DirectoryInfo(folder);
|
|
if (dirInfo.Exists)
|
|
{
|
|
files.AddRange(dirInfo.GetFiles("*.log").Where(f => f.LastWriteTime > DateTime.Today.AddDays(-MAX_DAYS)).Select(logFile => logFile.FullName));
|
|
}
|
|
|
|
// Logs/<server>
|
|
folder = Path.Combine(Config.Default.DataPath, Config.Default.LogsRelativePath, this.Settings.ProfileID.ToLower());
|
|
dirInfo = new DirectoryInfo(folder);
|
|
if (dirInfo.Exists)
|
|
{
|
|
files.AddRange(dirInfo.GetFiles("*.*", SearchOption.AllDirectories).Where(f => f.LastWriteTime > DateTime.Today.AddDays(-MAX_DAYS)).Select(logFile => logFile.FullName));
|
|
}
|
|
|
|
// Profile
|
|
file = this.Settings.GetProfileFile();
|
|
if (File.Exists(file))
|
|
{
|
|
var profileFile = ServerProfile.LoadFromProfileFile(file, null);
|
|
if (profileFile != null)
|
|
{
|
|
profileFile.AdminPassword = "obfuscated";
|
|
profileFile.ServerPassword = "obfuscated";
|
|
profileFile.RconPassword = "obfuscated";
|
|
profileFile.BranchPassword = "obfuscated";
|
|
obfuscateFiles.Add(file, profileFile.ToOutputString());
|
|
}
|
|
}
|
|
|
|
// <data folder>\SteamCMD\steamapps\workshop\content\<app id>
|
|
folder = Path.Combine(Config.Default.DataPath, CommonConfig.Default.SteamCmdRelativePath, Config.Default.AppSteamWorkshopFolderRelativePath);
|
|
if (Directory.Exists(folder))
|
|
{
|
|
foreach (var modFolder in Directory.GetDirectories(folder))
|
|
{
|
|
file = Path.Combine(modFolder, Config.Default.LastUpdatedTimeFile);
|
|
if (File.Exists(file)) files.Add(file);
|
|
}
|
|
}
|
|
|
|
// <server cache>
|
|
if (!string.IsNullOrWhiteSpace(Config.Default.AutoUpdate_CacheDir))
|
|
{
|
|
var branchName = string.IsNullOrWhiteSpace(this.Settings.BranchName) ? Config.Default.DefaultServerBranchName : this.Settings.BranchName;
|
|
file = IOUtils.NormalizePath(Path.Combine(Config.Default.AutoUpdate_CacheDir, $"{Config.Default.ServerBranchFolderPrefix}{branchName}", Config.Default.LastUpdatedTimeFile));
|
|
if (File.Exists(file)) files.Add(file);
|
|
}
|
|
|
|
// scheduled tasks (profile level)
|
|
var taskKey = this.Settings.GetProfileKey();
|
|
|
|
var taskXML = TaskSchedulerUtils.GetScheduleTaskInformation(TaskSchedulerUtils.TaskType.AutoStart, taskKey, null);
|
|
if (!string.IsNullOrWhiteSpace(taskXML))
|
|
obfuscateFiles.Add($"Task-{TaskSchedulerUtils.TaskType.AutoStart}.xml", taskXML);
|
|
|
|
taskXML = TaskSchedulerUtils.GetScheduleTaskInformation(TaskSchedulerUtils.TaskType.AutoShutdown, taskKey, "#1");
|
|
if (!string.IsNullOrWhiteSpace(taskXML))
|
|
obfuscateFiles.Add($"Task-{TaskSchedulerUtils.TaskType.AutoShutdown}-#1.xml", taskXML);
|
|
|
|
taskXML = TaskSchedulerUtils.GetScheduleTaskInformation(TaskSchedulerUtils.TaskType.AutoShutdown, taskKey, "#2");
|
|
if (!string.IsNullOrWhiteSpace(taskXML))
|
|
obfuscateFiles.Add($"Task-{TaskSchedulerUtils.TaskType.AutoShutdown}-#2.xml", taskXML);
|
|
|
|
// scheduled tasks (manager level)
|
|
taskKey = TaskSchedulerUtils.ComputeKey(Config.Default.DataPath);
|
|
|
|
taskXML = TaskSchedulerUtils.GetScheduleTaskInformation(TaskSchedulerUtils.TaskType.AutoBackup, taskKey, null);
|
|
if (!string.IsNullOrWhiteSpace(taskXML))
|
|
obfuscateFiles.Add($"Task-{TaskSchedulerUtils.TaskType.AutoBackup}.xml", taskXML);
|
|
|
|
taskXML = TaskSchedulerUtils.GetScheduleTaskInformation(TaskSchedulerUtils.TaskType.AutoUpdate, taskKey, null);
|
|
if (!string.IsNullOrWhiteSpace(taskXML))
|
|
obfuscateFiles.Add($"Task-{TaskSchedulerUtils.TaskType.AutoUpdate}.xml", taskXML);
|
|
|
|
// archive comment - mostly global config settings
|
|
var comment = new StringBuilder();
|
|
comment.AppendLine($"Windows Platform: {Environment.OSVersion.Platform}");
|
|
comment.AppendLine($"Windows Version: {Environment.OSVersion.VersionString}");
|
|
|
|
comment.AppendLine($"Game Server Version: {this.Settings.LastInstalledVersion}");
|
|
comment.AppendLine($"Server Manager Version: {App.Instance.Version}");
|
|
comment.AppendLine($"Server Manager Code: {Config.Default.ServerManagerCode}");
|
|
comment.AppendLine($"Server Manager Key: {Config.Default.ServerManagerUniqueKey}");
|
|
comment.AppendLine($"Server Manager Directory: {Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)}");
|
|
|
|
comment.AppendLine($"MachinePublicIP: {Config.Default.MachinePublicIP}");
|
|
comment.AppendLine($"Data Directory: {Config.Default.DataPath}");
|
|
comment.AppendLine($"Profiles Directory: {Config.Default.ConfigPath}");
|
|
if (!string.IsNullOrWhiteSpace(Config.Default.BackupPath))
|
|
comment.AppendLine($"Backup Directory: {Config.Default.BackupPath}");
|
|
else
|
|
comment.AppendLine($"Backup Directory: *{Path.Combine(Config.Default.DataPath, Config.Default.BackupRelativePath)}");
|
|
comment.AppendLine($"Server Directory: {this.Settings.InstallDirectory}");
|
|
|
|
comment.AppendLine($"IsAdministrator: {SecurityUtils.IsAdministrator()}");
|
|
comment.AppendLine($"RunAsAdministratorPrompt: {Config.Default.RunAsAdministratorPrompt}");
|
|
comment.AppendLine($"MainWindow_WindowState: {Config.Default.MainWindow_WindowState}");
|
|
comment.AppendLine($"MainWindow_MinimizeToTray: {Config.Default.MainWindow_MinimizeToTray}");
|
|
comment.AppendLine($"ManageFirewallAutomatically: {Config.Default.ManageFirewallAutomatically}");
|
|
comment.AppendLine($"ValidateProfileOnServerStart: {Config.Default.ValidateProfileOnServerStart}");
|
|
comment.AppendLine($"SteamCMD File: {SteamCmdUpdater.GetSteamCmdFile(Config.Default.DataPath)}");
|
|
comment.AppendLine($"SteamCmdRedirectOutput: {Config.Default.SteamCmdRedirectOutput}");
|
|
comment.AppendLine($"SteamCmd_UseAnonymousCredentials: {Config.Default.SteamCmd_UseAnonymousCredentials}");
|
|
comment.AppendLine($"SteamCmd_Username Set: {!string.IsNullOrWhiteSpace(Config.Default.SteamCmd_Username)}");
|
|
comment.AppendLine($"SteamCmd_Password Set: {!string.IsNullOrWhiteSpace(Config.Default.SteamCmd_Password)}");
|
|
comment.AppendLine($"SteamAPIKey: {!string.IsNullOrWhiteSpace(CommonConfig.Default.SteamAPIKey)}");
|
|
|
|
comment.AppendLine($"AutoBackup_EnableBackup: {Config.Default.AutoBackup_EnableBackup}");
|
|
comment.AppendLine($"AutoBackup_BackupPeriod: {Config.Default.AutoBackup_BackupPeriod}");
|
|
comment.AppendLine($"AutoBackup_DeleteOldFiles: {Config.Default.AutoBackup_DeleteOldFiles}");
|
|
comment.AppendLine($"AutoBackup_DeleteInterval: {Config.Default.AutoBackup_DeleteInterval}");
|
|
|
|
comment.AppendLine($"AutoUpdate_EnableUpdate: {Config.Default.AutoUpdate_EnableUpdate}");
|
|
comment.AppendLine($"AutoUpdate_CacheDir: {Config.Default.AutoUpdate_CacheDir}");
|
|
comment.AppendLine($"AutoUpdate_UpdatePeriod: {Config.Default.AutoUpdate_UpdatePeriod}");
|
|
comment.AppendLine($"AutoUpdate_UseSmartCopy: {Config.Default.AutoUpdate_UseSmartCopy}");
|
|
comment.AppendLine($"AutoUpdate_RetryOnFail: {Config.Default.AutoUpdate_RetryOnFail}");
|
|
comment.AppendLine($"AutoUpdate_ShowUpdateReason: {Config.Default.AutoUpdate_ShowUpdateReason}");
|
|
comment.AppendLine($"AutoUpdate_ValidateServerFiles: {Config.Default.AutoUpdate_ValidateServerFiles}");
|
|
comment.AppendLine($"AutoUpdate_OverrideServerStartup: {Config.Default.AutoUpdate_OverrideServerStartup}");
|
|
|
|
comment.AppendLine($"AutoRestart_EnabledGracePeriod: {Config.Default.AutoRestart_EnabledGracePeriod}");
|
|
comment.AppendLine($"AutoRestart_GracePeriod: {Config.Default.AutoRestart_GracePeriod}");
|
|
|
|
comment.AppendLine($"ServerShutdown_EnableWorldSave: {Config.Default.ServerShutdown_EnableWorldSave}");
|
|
comment.AppendLine($"ServerShutdown_CheckForOnlinePlayers: {Config.Default.ServerShutdown_CheckForOnlinePlayers}");
|
|
comment.AppendLine($"ServerShutdown_SendShutdownMessages: {Config.Default.ServerShutdown_SendShutdownMessages}");
|
|
comment.AppendLine($"ServerShutdown_GracePeriod: {Config.Default.ServerShutdown_GracePeriod}");
|
|
comment.AppendLine($"ServerUpdate_UpdateModsWhenUpdatingServer: {Config.Default.ServerUpdate_UpdateModsWhenUpdatingServer}");
|
|
comment.AppendLine($"ServerUpdate_ForceCopyMods: {Config.Default.ServerUpdate_ForceCopyMods}");
|
|
comment.AppendLine($"ServerUpdate_ForceUpdateMods: {Config.Default.ServerUpdate_ForceUpdateMods}");
|
|
comment.AppendLine($"ServerUpdate_ForceUpdateModsIfNoSteamInfo: {Config.Default.ServerUpdate_ForceUpdateModsIfNoSteamInfo}");
|
|
comment.AppendLine($"ServerUpdate_OnServerStart: {Config.Default.ServerUpdate_OnServerStart}");
|
|
|
|
comment.AppendLine($"DiscordBotEnabled: {Config.Default.DiscordBotEnabled}");
|
|
comment.AppendLine($"HasDiscordBotToken: {!string.IsNullOrWhiteSpace(Config.Default.DiscordBotToken)}");
|
|
comment.AppendLine($"DiscordBotServerId: {Config.Default.DiscordBotServerId}");
|
|
comment.AppendLine($"DiscordBotPrefix: {Config.Default.DiscordBotPrefix}");
|
|
comment.AppendLine($"AllowDiscordBackup: {Config.Default.AllowDiscordBackup}");
|
|
comment.AppendLine($"AllowDiscordRestart: {Config.Default.AllowDiscordRestart}");
|
|
comment.AppendLine($"AllowDiscordShutdown: {Config.Default.AllowDiscordShutdown}");
|
|
comment.AppendLine($"AllowDiscordStart: {Config.Default.AllowDiscordStart}");
|
|
comment.AppendLine($"AllowDiscordStop: {Config.Default.AllowDiscordStop}");
|
|
comment.AppendLine($"AllowDiscordUpdate: {Config.Default.AllowDiscordUpdate}");
|
|
|
|
comment.AppendLine($"EmailNotify_AutoRestart: {Config.Default.EmailNotify_AutoRestart}");
|
|
comment.AppendLine($"EmailNotify_AutoBackup: {Config.Default.EmailNotify_AutoBackup}");
|
|
comment.AppendLine($"EmailNotify_AutoUpdate: {Config.Default.EmailNotify_AutoUpdate}");
|
|
comment.AppendLine($"EmailNotify_ShutdownRestart: {Config.Default.EmailNotify_ShutdownRestart}");
|
|
|
|
comment.AppendLine($"ServerShutdown_UseShutdownCommand: {Config.Default.ServerShutdown_UseShutdownCommand}");
|
|
comment.AppendLine($"ServerShutdown_WorldSaveDelay: {Config.Default.ServerShutdown_WorldSaveDelay}");
|
|
comment.AppendLine($"BackupWorldFile: {Config.Default.BackupWorldFile}");
|
|
comment.AppendLine($"AutoUpdate_VerifyServerAfterUpdate: {Config.Default.AutoUpdate_VerifyServerAfterUpdate}");
|
|
comment.AppendLine($"UpdateDirectoryPermissions: {Config.Default.UpdateDirectoryPermissions}");
|
|
|
|
var zipFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), this.Settings.ProfileID + ".zip");
|
|
if (File.Exists(zipFile)) File.Delete(zipFile);
|
|
|
|
ZipUtils.ZipFiles(zipFile, files, comment.ToString());
|
|
foreach (var kvp in obfuscateFiles)
|
|
{
|
|
ZipUtils.ZipAFile(zipFile, kvp.Key, kvp.Value);
|
|
}
|
|
|
|
var message = _globalizer.GetResourceString("ServerSettings_SupportZipSuccessLabel").Replace("{filename}", Path.GetFileName(zipFile));
|
|
MessageBox.Show(message, _globalizer.GetResourceString("ServerSettings_SupportZipTitle"), MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_SupportZipErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
finally
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() => this.Cursor = cursor);
|
|
}
|
|
}
|
|
|
|
private async void ValidateProfile_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var cursor = this.Cursor;
|
|
|
|
try
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() => this.Cursor = Cursors.Wait);
|
|
await Task.Delay(500);
|
|
|
|
var result = this.Settings.Validate(true, out string validationMessage);
|
|
|
|
if (result)
|
|
MessageBox.Show(_globalizer.GetResourceString("ServerSettings_ProfileValidateSuccessLabel"), _globalizer.GetResourceString("ServerSettings_ProfileValidateTitle"), MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
else
|
|
MessageBox.Show(validationMessage, _globalizer.GetResourceString("ServerSettings_ProfileValidateTitle"), MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_ProfileValidateErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
finally
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() => this.Cursor = cursor);
|
|
}
|
|
}
|
|
|
|
private void SelectInstallDirectory_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var dialog = new CommonOpenFileDialog()
|
|
{
|
|
IsFolderPicker = true,
|
|
Title = _globalizer.GetResourceString("ServerSettings_InstallServer_Title")
|
|
};
|
|
if (!String.IsNullOrWhiteSpace(Settings.InstallDirectory))
|
|
{
|
|
dialog.InitialDirectory = Settings.InstallDirectory;
|
|
}
|
|
|
|
var result = dialog.ShowDialog(Window.GetWindow(this));
|
|
if (result == CommonFileDialogResult.Ok)
|
|
{
|
|
Settings.ChangeInstallationFolder(dialog.FileName);
|
|
}
|
|
}
|
|
|
|
private void Load_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (!Directory.Exists(Config.Default.ConfigPath))
|
|
{
|
|
Directory.CreateDirectory(Config.Default.ConfigPath);
|
|
}
|
|
|
|
var dialog = new CommonOpenFileDialog()
|
|
{
|
|
EnsureFileExists = true,
|
|
InitialDirectory = Config.Default.ConfigPath,
|
|
Multiselect = false,
|
|
Title = _globalizer.GetResourceString("ServerSettings_LoadConfig_Title")
|
|
};
|
|
dialog.Filters.Add(new CommonFileDialogFilter("Profile", Config.Default.LoadProfileExtensionList));
|
|
|
|
if (dialog.ShowDialog(Window.GetWindow(this)) == CommonFileDialogResult.Ok)
|
|
{
|
|
try
|
|
{
|
|
this.Server.ImportFromPath(dialog.FileName, Settings);
|
|
this.Server.Profile.ResetProfileId();
|
|
|
|
this.Settings = this.Server.Profile;
|
|
this.Runtime = this.Server.Runtime;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(String.Format(_globalizer.GetResourceString("ServerSettings_LoadConfig_ErrorLabel"), dialog.FileName, ex.Message, ex.StackTrace), _globalizer.GetResourceString("ServerSettings_LoadConfig_ErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Exclamation);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ShowCmd_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var cmdLine = new CommandLineWindow(String.Format("{0} {1}", this.Runtime.GetServerExe(), this.Settings.GetServerArgs()))
|
|
{
|
|
Owner = Window.GetWindow(this)
|
|
};
|
|
cmdLine.ShowDialog();
|
|
}
|
|
|
|
private void ServerAutoSettings_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
MessageBox.Show(_globalizer.GetResourceString("ServerSettings_ServerAutoSettings_ErrorLabel"), _globalizer.GetResourceString("ServerSettings_ServerAutoSettings_ErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
|
|
private async void SaveBackup_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() => this.Cursor = System.Windows.Input.Cursors.Wait);
|
|
|
|
var app = new ServerApp(true)
|
|
{
|
|
DeleteOldServerBackupFiles = !Config.Default.AutoBackup_EnableBackup,
|
|
SendEmails = false,
|
|
OutputLogs = false,
|
|
ServerProcess = ServerProcessType.Backup,
|
|
};
|
|
|
|
var profile = ServerProfileSnapshot.Create(Server.Profile);
|
|
|
|
var exitCode = await Task.Run(() => app.PerformProfileBackup(profile, CancellationToken.None));
|
|
if (exitCode != ServerApp.EXITCODE_NORMALEXIT && exitCode != ServerApp.EXITCODE_CANCELLED)
|
|
throw new ApplicationException($"An error occured during the backup process - ExitCode: {exitCode}");
|
|
|
|
MessageBox.Show(_globalizer.GetResourceString("ServerSettings_BackupServer_SuccessfulLabel"), _globalizer.GetResourceString("ServerSettings_BackupServer_Title"), MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_BackupServer_FailedTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
finally
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() => this.Cursor = null);
|
|
}
|
|
}
|
|
|
|
private void SaveRestore_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var window = new WorldSaveRestoreWindow(Server.Profile)
|
|
{
|
|
Owner = Window.GetWindow(this)
|
|
};
|
|
window.Closed += Window_Closed;
|
|
window.ShowDialog();
|
|
}
|
|
|
|
private void HiddenField_GotFocus(object sender, RoutedEventArgs e)
|
|
{
|
|
if (sender is TextBox hideTextBox)
|
|
{
|
|
TextBox textBox = null;
|
|
if (Equals(hideTextBox, HideServerPasswordTextBox))
|
|
textBox = ServerPasswordTextBox;
|
|
if (Equals(hideTextBox, HideAdminPasswordTextBox))
|
|
textBox = AdminPasswordTextBox;
|
|
if (Equals(hideTextBox, HideRconPasswordTextBox))
|
|
textBox = RconPasswordTextBox;
|
|
if (Equals(hideTextBox, HideBranchPasswordTextBox))
|
|
textBox = BranchPasswordTextBox;
|
|
|
|
if (textBox != null)
|
|
{
|
|
textBox.Visibility = System.Windows.Visibility.Visible;
|
|
hideTextBox.Visibility = System.Windows.Visibility.Collapsed;
|
|
textBox.Focus();
|
|
}
|
|
|
|
UpdateLayout();
|
|
}
|
|
}
|
|
|
|
private void HiddenField_LostFocus(object sender, RoutedEventArgs e)
|
|
{
|
|
if (sender is TextBox textBox)
|
|
{
|
|
TextBox hideTextBox = null;
|
|
if (textBox == ServerPasswordTextBox)
|
|
hideTextBox = HideServerPasswordTextBox;
|
|
if (textBox == AdminPasswordTextBox)
|
|
hideTextBox = HideAdminPasswordTextBox;
|
|
if (textBox == RconPasswordTextBox)
|
|
hideTextBox = HideRconPasswordTextBox;
|
|
if (textBox == BranchPasswordTextBox)
|
|
hideTextBox = HideBranchPasswordTextBox;
|
|
|
|
if (hideTextBox != null)
|
|
{
|
|
hideTextBox.Visibility = System.Windows.Visibility.Visible;
|
|
textBox.Visibility = System.Windows.Visibility.Collapsed;
|
|
}
|
|
UpdateLayout();
|
|
}
|
|
}
|
|
|
|
private void ComboBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
|
|
{
|
|
var comboBox = sender as ComboBox;
|
|
if (comboBox == null)
|
|
return;
|
|
|
|
if (comboBox.IsDropDownOpen)
|
|
return;
|
|
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void ComboBoxItemList_LostFocus(object sender, RoutedEventArgs e)
|
|
{
|
|
var comboBox = sender as ComboBox;
|
|
if (comboBox == null)
|
|
return;
|
|
|
|
if (comboBox.SelectedItem == null)
|
|
{
|
|
var text = comboBox.Text;
|
|
|
|
var source = comboBox.ItemsSource as ComboBoxItemList;
|
|
source?.Add(new Common.Model.ComboBoxItem
|
|
{
|
|
ValueMember = text,
|
|
DisplayMember = text,
|
|
});
|
|
|
|
comboBox.SelectedValue = text;
|
|
}
|
|
|
|
var expression = comboBox.GetBindingExpression(Selector.SelectedValueProperty);
|
|
expression?.UpdateSource();
|
|
|
|
expression = comboBox.GetBindingExpression(ComboBox.TextProperty);
|
|
expression?.UpdateSource();
|
|
}
|
|
|
|
private void OutOfDateModUpdate_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
this.Runtime?.ResetModCheckTimer();
|
|
}
|
|
|
|
private void ProfileName_SourceUpdated(object sender, DataTransferEventArgs e)
|
|
{
|
|
Settings.UpdateProfileToolTip();
|
|
}
|
|
|
|
private void ServerName_SourceUpdated(object sender, DataTransferEventArgs e)
|
|
{
|
|
Settings.ValidateServerName();
|
|
}
|
|
|
|
private void ServerPort_SourceUpdated(object sender, DataTransferEventArgs e)
|
|
{
|
|
// force the porperty to be updated.
|
|
Settings.ServerPort = Settings.ServerPort;
|
|
}
|
|
|
|
private void MapName_SourceUpdated(object sender, DataTransferEventArgs e)
|
|
{
|
|
Settings.SyncMapSaveFileName();
|
|
}
|
|
|
|
private void MOTD_SourceUpdated(object sender, DataTransferEventArgs e)
|
|
{
|
|
Settings.ValidateMOTD();
|
|
}
|
|
|
|
private void SyncProfile_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var window = new ProfileSyncWindow(ServerManager, Server.Profile)
|
|
{
|
|
Owner = Window.GetWindow(this)
|
|
};
|
|
window.Closed += Window_Closed;
|
|
window.ShowDialog();
|
|
}
|
|
|
|
private void OpenAffinity_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var window = new ProcessorAffinityWindow(Server.Profile.ProfileName, Server.Profile.ProcessAffinity)
|
|
{
|
|
Owner = Window.GetWindow(this)
|
|
};
|
|
window.Closed += Window_Closed;
|
|
var result = window.ShowDialog();
|
|
|
|
if (result.HasValue && result.Value)
|
|
{
|
|
Server.Profile.ProcessAffinity = window.AffinityValue;
|
|
}
|
|
}
|
|
|
|
#region Server Files
|
|
private void AddBlacklistedPlayer_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var window = new AddUserWindow()
|
|
{
|
|
Owner = Window.GetWindow(this)
|
|
};
|
|
window.Closed += Window_Closed;
|
|
var result = window.ShowDialog();
|
|
|
|
if (result.HasValue && result.Value)
|
|
{
|
|
try
|
|
{
|
|
Settings.DestroyServerFilesWatcher();
|
|
|
|
var steamIdsString = window.Users;
|
|
var steamIds = steamIdsString.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
|
|
var steamUsers = SteamUtils.GetSteamUserDetails(steamIds.ToList());
|
|
var steamUserList = PlayerUserList.GetList(steamUsers, steamIds);
|
|
Settings.ServerFilesBlacklisted.AddRange(steamUserList);
|
|
|
|
Settings.SaveServerFileBlacklisted();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, "Add Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
finally
|
|
{
|
|
Settings.SetupServerFilesWatcher();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void AddWhitelistedPlayer_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var window = new AddUserWindow()
|
|
{
|
|
Owner = Window.GetWindow(this)
|
|
};
|
|
window.Closed += Window_Closed;
|
|
var result = window.ShowDialog();
|
|
|
|
if (result.HasValue && result.Value)
|
|
{
|
|
try
|
|
{
|
|
Settings.DestroyServerFilesWatcher();
|
|
|
|
var steamIdsString = window.Users;
|
|
var steamIds = steamIdsString.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
|
|
var steamUsers = SteamUtils.GetSteamUserDetails(steamIds.ToList());
|
|
var steamUserList = PlayerUserList.GetList(steamUsers, steamIds);
|
|
Settings.ServerFilesWhitelisted.AddRange(steamUserList);
|
|
|
|
Settings.SaveServerFileWhitelisted();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, "Add Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
finally
|
|
{
|
|
Settings.SetupServerFilesWatcher();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ClearBlacklistedPlayers_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (MessageBox.Show(_globalizer.GetResourceString("ServerSettings_ClearLabel"), _globalizer.GetResourceString("ServerSettings_ClearTitle"), MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
|
|
return;
|
|
|
|
try
|
|
{
|
|
Settings.DestroyServerFilesWatcher();
|
|
|
|
Settings.ServerFilesBlacklisted.Clear();
|
|
Settings.SaveServerFileBlacklisted();
|
|
}
|
|
finally
|
|
{
|
|
Settings.SetupServerFilesWatcher();
|
|
}
|
|
}
|
|
|
|
private void ClearWhitelistedPlayers_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (MessageBox.Show(_globalizer.GetResourceString("ServerSettings_ClearLabel"), _globalizer.GetResourceString("ServerSettings_ClearTitle"), MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
|
|
return;
|
|
|
|
try
|
|
{
|
|
Settings.DestroyServerFilesWatcher();
|
|
|
|
Settings.ServerFilesWhitelisted.Clear();
|
|
Settings.SaveServerFileWhitelisted();
|
|
}
|
|
finally
|
|
{
|
|
Settings.SetupServerFilesWatcher();
|
|
}
|
|
}
|
|
|
|
private async void ReloadBlacklistedPlayers_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var cursor = this.Cursor;
|
|
|
|
try
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() => this.Cursor = Cursors.Wait);
|
|
await Task.Delay(500);
|
|
|
|
Settings.LoadServerFiles(true, false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, "Refresh Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
finally
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() => this.Cursor = cursor);
|
|
}
|
|
}
|
|
|
|
private async void ReloadWhitelistedPlayers_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var cursor = this.Cursor;
|
|
|
|
try
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() => this.Cursor = Cursors.Wait);
|
|
await Task.Delay(500);
|
|
|
|
Settings.LoadServerFiles(false, true);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, "Refresh Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
finally
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() => this.Cursor = cursor);
|
|
}
|
|
}
|
|
|
|
private void RemoveBlacklistedPlayer_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (MessageBox.Show(_globalizer.GetResourceString("ServerSettings_DeleteLabel"), _globalizer.GetResourceString("ServerSettings_DeleteTitle"), MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
|
|
return;
|
|
|
|
try
|
|
{
|
|
Settings.DestroyServerFilesWatcher();
|
|
|
|
var mod = ((PlayerUserItem)((Button)e.Source).DataContext);
|
|
Settings.ServerFilesBlacklisted.Remove(mod.PlayerId);
|
|
|
|
Settings.SaveServerFileBlacklisted();
|
|
}
|
|
finally
|
|
{
|
|
Settings.SetupServerFilesWatcher();
|
|
}
|
|
}
|
|
|
|
private void RemoveWhitelistedPlayer_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (MessageBox.Show(_globalizer.GetResourceString("ServerSettings_DeleteLabel"), _globalizer.GetResourceString("ServerSettings_DeleteTitle"), MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
|
|
return;
|
|
|
|
try
|
|
{
|
|
Settings.DestroyServerFilesWatcher();
|
|
|
|
var mod = ((PlayerUserItem)((Button)e.Source).DataContext);
|
|
Settings.ServerFilesWhitelisted.Remove(mod.PlayerId);
|
|
|
|
Settings.SaveServerFileWhitelisted();
|
|
}
|
|
finally
|
|
{
|
|
Settings.SetupServerFilesWatcher();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
public void RefreshBaseGameMapsList()
|
|
{
|
|
var newList = new ComboBoxItemList();
|
|
|
|
foreach (var item in GameData.GetGameMaps())
|
|
{
|
|
item.DisplayMember = GameData.FriendlyMapNameForClass(item.ValueMember);
|
|
newList.Add(item);
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(this.Settings.ServerMap))
|
|
{
|
|
if (!newList.Any(m => m.ValueMember.Equals(this.Settings.ServerMap, StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
newList.Add(new Common.Model.ComboBoxItem
|
|
{
|
|
DisplayMember = GameData.FriendlyMapNameForClass(this.Settings.ServerMap),
|
|
ValueMember = this.Settings.ServerMap,
|
|
});
|
|
}
|
|
}
|
|
|
|
var profileServerMap = this.Settings.ServerMap;
|
|
|
|
this.BaseGameMaps = newList;
|
|
this.GameMapComboBox.SelectedValue = profileServerMap;
|
|
}
|
|
|
|
public void RefreshBaseBranchesList()
|
|
{
|
|
var newList = new ComboBoxItemList();
|
|
|
|
foreach (var item in GameData.GetBranches())
|
|
{
|
|
item.DisplayMember = GameData.FriendlyBranchName(string.IsNullOrWhiteSpace(item.ValueMember) ? Config.Default.DefaultServerBranchName : item.ValueMember);
|
|
newList.Add(item);
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(this.Settings.BranchName))
|
|
{
|
|
if (!newList.Any(m => m.ValueMember.Equals(this.Settings.BranchName, StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
newList.Add(new Common.Model.ComboBoxItem
|
|
{
|
|
DisplayMember = GameData.FriendlyBranchName(this.Settings.BranchName),
|
|
ValueMember = this.Settings.BranchName,
|
|
});
|
|
}
|
|
}
|
|
|
|
var profileBranchName = this.Settings.BranchName;
|
|
|
|
this.BaseBranches = newList;
|
|
this.BranchComboBox.SelectedValue = profileBranchName;
|
|
}
|
|
|
|
public void RefreshProcessPrioritiesList()
|
|
{
|
|
var newList = new ComboBoxItemList();
|
|
|
|
foreach (var priority in ProcessUtils.GetProcessPriorityList())
|
|
{
|
|
newList.Add(new Common.Model.ComboBoxItem(priority, _globalizer.GetResourceString($"Priority_{priority}")));
|
|
}
|
|
|
|
var profilePriority = this.Settings.ProcessPriority;
|
|
|
|
this.ProcessPriorities = newList;
|
|
this.ProcessPriorityComboBox.SelectedValue = profilePriority;
|
|
}
|
|
|
|
public void RefreshServerRegionsList()
|
|
{
|
|
var newList = new ComboBoxItemList();
|
|
|
|
foreach (var item in GameData.GetServerRegions())
|
|
{
|
|
item.DisplayMember = GameData.FriendlyServerRegionName(item.ValueMember);
|
|
newList.Add(item);
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(this.Settings.ServerRegion))
|
|
{
|
|
if (!newList.Any(m => m.ValueMember.Equals(this.Settings.ServerRegion, StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
newList.Add(new Common.Model.ComboBoxItem
|
|
{
|
|
DisplayMember = GameData.FriendlyServerRegionName(this.Settings.ServerRegion),
|
|
ValueMember = this.Settings.ServerRegion,
|
|
});
|
|
}
|
|
}
|
|
|
|
var serverRegion = this.Settings.ServerRegion;
|
|
|
|
this.ServerRegions = newList;
|
|
this.ServerRegionsComboBox.SelectedValue = serverRegion;
|
|
}
|
|
|
|
private void ReinitializeNetworkAdapters()
|
|
{
|
|
var adapters = NetworkUtils.GetAvailableIPV4NetworkAdapters();
|
|
|
|
//
|
|
// Filter out self-assigned addresses
|
|
//
|
|
adapters.RemoveAll(a => a.IPAddress.StartsWith("169.254."));
|
|
adapters.Insert(0, new NetworkAdapterEntry(String.Empty, _globalizer.GetResourceString("ServerSettings_LocalIPGameChooseLabel")));
|
|
var savedServerIp = this.Settings.ServerIP;
|
|
this.NetworkInterfaces = adapters;
|
|
this.Settings.ServerIP = savedServerIp;
|
|
|
|
|
|
if (!String.IsNullOrWhiteSpace(this.Settings.ServerIP))
|
|
{
|
|
if (adapters.FirstOrDefault(a => String.Equals(a.IPAddress, this.Settings.ServerIP, StringComparison.OrdinalIgnoreCase)) == null)
|
|
{
|
|
MessageBox.Show(
|
|
String.Format(_globalizer.GetResourceString("ServerSettings_LocalIP_ErrorLabel"), this.Settings.ServerIP),
|
|
_globalizer.GetResourceString("ServerSettings_LocalIP_ErrorTitle"),
|
|
MessageBoxButton.OK,
|
|
MessageBoxImage.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
public ICommand ResetActionCommand
|
|
{
|
|
get
|
|
{
|
|
return new RelayCommand<ServerSettingsResetAction>(
|
|
execute: (action) =>
|
|
{
|
|
if (MessageBox.Show(_globalizer.GetResourceString("ServerSettings_ResetLabel"), _globalizer.GetResourceString("ServerSettings_ResetTitle"), MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
|
|
return;
|
|
|
|
switch (action)
|
|
{
|
|
// sections
|
|
case ServerSettingsResetAction.AdministrationSection:
|
|
this.Settings.ResetAdministrationSection();
|
|
RefreshBaseGameMapsList();
|
|
RefreshBaseBranchesList();
|
|
RefreshProcessPrioritiesList();
|
|
RefreshServerRegionsList();
|
|
break;
|
|
|
|
case ServerSettingsResetAction.DiscordBotSection:
|
|
this.Settings.ResetDiscordBotSection();
|
|
break;
|
|
|
|
// Properties
|
|
case ServerSettingsResetAction.RconWindowExtents:
|
|
this.Settings.ResetRconWindowExtents();
|
|
break;
|
|
|
|
case ServerSettingsResetAction.ServerOptions:
|
|
this.Settings.ResetServerOptions();
|
|
break;
|
|
}
|
|
},
|
|
canExecute: (action) => true
|
|
);
|
|
}
|
|
}
|
|
|
|
public ICommand SaveCommand
|
|
{
|
|
get
|
|
{
|
|
return new RelayCommand<object>(
|
|
execute: async (parameter) =>
|
|
{
|
|
try
|
|
{
|
|
dockPanel.IsEnabled = false;
|
|
OverlayMessage.Content = _globalizer.GetResourceString("ServerSettings_OverlayMessage_SavingLabel");
|
|
OverlayGrid.Visibility = Visibility.Visible;
|
|
|
|
await Task.Delay(100);
|
|
|
|
// NOTE: This parameter is of type object and must be cast in most cases before use.
|
|
var server = parameter as Server;
|
|
if (server != null)
|
|
{
|
|
server.Profile.Save(false, false, (p, m, n) => { OverlayMessage.Content = m; });
|
|
|
|
RefreshBaseGameMapsList();
|
|
RefreshBaseBranchesList();
|
|
RefreshProcessPrioritiesList();
|
|
RefreshServerRegionsList();
|
|
|
|
if (Config.Default.UpdateDirectoryPermissions)
|
|
{
|
|
OverlayMessage.Content = _globalizer.GetResourceString("ServerSettings_OverlayMessage_PermissionsLabel");
|
|
await Task.Delay(100);
|
|
|
|
server.Profile.UpdateDirectoryPermissions();
|
|
}
|
|
|
|
OverlayMessage.Content = _globalizer.GetResourceString("ServerSettings_OverlayMessage_SchedulesLabel");
|
|
await Task.Delay(100);
|
|
|
|
if (!server.Profile.UpdateSchedules())
|
|
{
|
|
MessageBox.Show(_globalizer.GetResourceString("ServerSettings_Save_UpdateSchedule_ErrorLabel"), _globalizer.GetResourceString("ServerSettings_Save_UpdateSchedule_ErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message, "Save Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
finally
|
|
{
|
|
OverlayGrid.Visibility = Visibility.Collapsed;
|
|
dockPanel.IsEnabled = true;
|
|
}
|
|
},
|
|
canExecute: (parameter) =>
|
|
{
|
|
return (parameter as Server) != null;
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
private async Task<bool> UpdateServer(bool establishLock, bool updateServer, bool updateMods, bool closeProgressWindow)
|
|
{
|
|
if (_upgradeCancellationSource != null)
|
|
return false;
|
|
|
|
ProgressWindow window = null;
|
|
Mutex mutex = null;
|
|
bool createdNew = !establishLock;
|
|
|
|
try
|
|
{
|
|
if (establishLock)
|
|
{
|
|
// try to establish a mutex for the profile.
|
|
mutex = new Mutex(true, ServerApp.GetMutexName(this.Server.Profile.InstallDirectory), out createdNew);
|
|
}
|
|
|
|
// check if the mutex was established
|
|
if (createdNew)
|
|
{
|
|
this._upgradeCancellationSource = new CancellationTokenSource();
|
|
|
|
window = new ProgressWindow(string.Format(_globalizer.GetResourceString("Progress_UpgradeServer_WindowTitle"), this.Server.Profile.ProfileName))
|
|
{
|
|
Owner = Window.GetWindow(this)
|
|
};
|
|
window.Closed += Window_Closed;
|
|
window.Show();
|
|
|
|
await Task.Delay(1000);
|
|
|
|
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
|
|
{
|
|
// display an error message and exit
|
|
MessageBox.Show(_globalizer.GetResourceString("ServerSettings_UpgradeServer_MutexFailedLabel"), _globalizer.GetResourceString("ServerSettings_UpgradeServer_FailedTitle"), MessageBoxButton.OK, MessageBoxImage.Information);
|
|
return false;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (window != null)
|
|
{
|
|
window.AddMessage(ex.Message);
|
|
window.AddMessage(ex.StackTrace);
|
|
}
|
|
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_UpgradeServer_FailedTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
|
return false;
|
|
}
|
|
finally
|
|
{
|
|
this._upgradeCancellationSource = null;
|
|
|
|
if (window != null)
|
|
{
|
|
window.CloseWindow();
|
|
if (closeProgressWindow)
|
|
window.Close();
|
|
}
|
|
|
|
if (mutex != null)
|
|
{
|
|
if (createdNew)
|
|
{
|
|
mutex.ReleaseMutex();
|
|
mutex.Dispose();
|
|
}
|
|
mutex = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void UpdateLastStartedDetails(bool updateProfile)
|
|
{
|
|
if (updateProfile)
|
|
{
|
|
// update the profile's last started time
|
|
this.Settings.LastStarted = DateTime.Now;
|
|
this.Settings.SaveProfile();
|
|
}
|
|
|
|
var date = Settings == null || Settings.LastStarted == DateTime.MinValue ? string.Empty : $"{Settings.LastStarted:G}";
|
|
this.ProfileLastStarted = $"{_globalizer.GetResourceString("ServerSettings_LastStartedLabel")} {date}";
|
|
}
|
|
#endregion
|
|
}
|
|
} |