using Microsoft.Win32.TaskScheduler;
using Newtonsoft.Json;
using NeXt.Vdf;
using NLog;
using ServerManagerTool.Common.Enums;
using ServerManagerTool.Common.JsonConverters;
using ServerManagerTool.Common.Lib;
using ServerManagerTool.Common.Model;
using ServerManagerTool.Common.Utils;
using ServerManagerTool.Enums;
using ServerManagerTool.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Windows;
using WPFSharp.Globalizer;
namespace ServerManagerTool.Lib
{
[DataContract]
public class ServerProfile : DependencyObject
{
private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private string _lastSaveLocation = string.Empty;
private FileSystemWatcher _serverFilesWatcher = null;
private ServerProfile()
{
ResetProfileId();
ServerPassword = SecurityUtils.GeneratePassword(16);
AdminPassword = SecurityUtils.GeneratePassword(16);
RconPassword = string.Empty;
BranchPassword = string.Empty;
ServerFilesBlacklisted = new PlayerUserList();
ServerFilesWhitelisted = new PlayerUserList();
// initialise the nullable properties
// initialise the complex properties
GetDefaultDirectories();
}
#region Properties
public static bool EnableServerFilesWatcher { get; set; } = true;
public static bool KeepConfigValues { get; set; } = false;
#region Profile Properties
public static readonly DependencyProperty ProfileIDProperty = DependencyProperty.Register(nameof(ProfileID), typeof(string), typeof(ServerProfile), new PropertyMetadata(Guid.NewGuid().ToString()));
[DataMember]
public string ProfileID
{
get { return (string)GetValue(ProfileIDProperty); }
set
{
SetValue(ProfileIDProperty, value);
UpdateProfileToolTip();
}
}
public static readonly DependencyProperty ProfileNameProperty = DependencyProperty.Register(nameof(ProfileName), typeof(string), typeof(ServerProfile), new PropertyMetadata(Config.Default.DefaultServerProfileName));
[DataMember]
public string ProfileName
{
get { return (string)GetValue(ProfileNameProperty); }
set
{
SetValue(ProfileNameProperty, value);
UpdateProfileToolTip();
}
}
public static readonly DependencyProperty InstallDirectoryProperty = DependencyProperty.Register(nameof(InstallDirectory), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
public string InstallDirectory
{
get { return (string)GetValue(InstallDirectoryProperty); }
set { SetValue(InstallDirectoryProperty, value); }
}
public static readonly DependencyProperty LastInstalledVersionProperty = DependencyProperty.Register(nameof(LastInstalledVersion), typeof(string), typeof(ServerProfile), new PropertyMetadata(new Version(0, 0).ToString()));
[DataMember]
public string LastInstalledVersion
{
get { return (string)GetValue(LastInstalledVersionProperty); }
set { SetValue(LastInstalledVersionProperty, value); }
}
public static readonly DependencyProperty SequenceProperty = DependencyProperty.Register(nameof(Sequence), typeof(int), typeof(ServerProfile), new PropertyMetadata(99));
[DataMember]
public int Sequence
{
get { return (int)GetValue(SequenceProperty); }
set { SetValue(SequenceProperty, value); }
}
public static readonly DependencyProperty LastStartedProperty = DependencyProperty.Register(nameof(LastStarted), typeof(DateTime), typeof(ServerProfile), new PropertyMetadata(DateTime.MinValue));
[DataMember]
public DateTime LastStarted
{
get { return (DateTime)GetValue(LastStartedProperty); }
set { SetValue(LastStartedProperty, value); }
}
public static readonly DependencyProperty ProfileToolTipProperty = DependencyProperty.Register(nameof(ProfileToolTip), typeof(string), typeof(ServerProfile), new PropertyMetadata(string.Empty));
public string ProfileToolTip
{
get { return (string)GetValue(ProfileToolTipProperty); }
set { SetValue(ProfileToolTipProperty, value); }
}
public string SortKey
{
get
{
return $"{Sequence:0000000000}|{ProfileName}|{ProfileID}";
}
}
#endregion
#region Administration
public static readonly DependencyProperty ServerNameProperty = DependencyProperty.Register(nameof(ServerName), typeof(string), typeof(ServerProfile), new PropertyMetadata(Config.Default.DefaultServerName));
[DataMember]
[IniFileEntry(IniFiles.Engine, IniSections.Engine_OnlineSubsystem, ServerProfileCategory.Administration)]
public string ServerName
{
get { return (string)GetValue(ServerNameProperty); }
set
{
SetValue(ServerNameProperty, value);
ValidateServerName();
}
}
public static readonly DependencyProperty ServerNameLengthProperty = DependencyProperty.Register(nameof(ServerNameLength), typeof(int), typeof(ServerProfile), new PropertyMetadata(0));
public int ServerNameLength
{
get { return (int)GetValue(ServerNameLengthProperty); }
set { SetValue(ServerNameLengthProperty, value); }
}
public static readonly DependencyProperty ServerNameLengthToLongProperty = DependencyProperty.Register(nameof(ServerNameLengthToLong), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
public bool ServerNameLengthToLong
{
get { return (bool)GetValue(ServerNameLengthToLongProperty); }
set { SetValue(ServerNameLengthToLongProperty, value); }
}
public static readonly DependencyProperty ServerPasswordProperty = DependencyProperty.Register(nameof(ServerPassword), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
[IniFileEntry(IniFiles.Engine, IniSections.Engine_OnlineSubsystem, ServerProfileCategory.Administration)]
public string ServerPassword
{
get { return (string)GetValue(ServerPasswordProperty); }
set { SetValue(ServerPasswordProperty, value); }
}
public static readonly DependencyProperty AdminPasswordProperty = DependencyProperty.Register(nameof(AdminPassword), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
[IniFileEntry(IniFiles.ServerSettings, IniSections.ServerSettings_ServerSettings, ServerProfileCategory.Administration)]
public string AdminPassword
{
get { return (string)GetValue(AdminPasswordProperty); }
set { SetValue(AdminPasswordProperty, value); }
}
public static readonly DependencyProperty ServerIPProperty = DependencyProperty.Register(nameof(ServerIP), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
public string ServerIP
{
get { return (string)GetValue(ServerIPProperty); }
set { SetValue(ServerIPProperty, value); }
}
public static readonly DependencyProperty ServerPortProperty = DependencyProperty.Register(nameof(ServerPort), typeof(int), typeof(ServerProfile), new PropertyMetadata(7777));
[DataMember]
[IniFileEntry(IniFiles.Engine, IniSections.Engine_URL, ServerProfileCategory.Administration, "Port")]
public int ServerPort
{
get { return (int)GetValue(ServerPortProperty); }
set
{
SetValue(ServerPortProperty, value);
ServerPeerPort = value + 1;
}
}
public static readonly DependencyProperty ServerPeerPortProperty = DependencyProperty.Register(nameof(ServerPeerPort), typeof(int), typeof(ServerProfile), new PropertyMetadata(7778));
[IniFileEntry(IniFiles.Engine, IniSections.Engine_URL, ServerProfileCategory.Administration, "PeerPort", ClearWhenOff = nameof(KeepConfigValues))]
public int ServerPeerPort
{
get { return (int)GetValue(ServerPeerPortProperty); }
set { SetValue(ServerPeerPortProperty, value); }
}
public static readonly DependencyProperty QueryPortProperty = DependencyProperty.Register(nameof(QueryPort), typeof(int), typeof(ServerProfile), new PropertyMetadata(27015));
[DataMember]
[IniFileEntry(IniFiles.Engine, IniSections.Engine_OnlineSubsystemSteam, ServerProfileCategory.Administration, "GameServerQueryPort", ClearWhenOff = nameof(KeepConfigValues))]
public int QueryPort
{
get { return (int)GetValue(QueryPortProperty); }
set { SetValue(QueryPortProperty, value); }
}
public static readonly DependencyProperty ServerMapProperty = DependencyProperty.Register(nameof(ServerMap), typeof(string), typeof(ServerProfile), new PropertyMetadata("ConanSandbox"));
[DataMember]
public string ServerMap
{
get { return (string)GetValue(ServerMapProperty); }
set
{
SetValue(ServerMapProperty, value);
SyncMapSaveFileName();
}
}
public static readonly DependencyProperty ServerMapSaveFileNameProperty = DependencyProperty.Register(nameof(ServerMapSaveFileName), typeof(string), typeof(ServerProfile), new PropertyMetadata("game.db"));
[DataMember]
public string ServerMapSaveFileName
{
get { return (string)GetValue(ServerMapSaveFileNameProperty); }
set { SetValue(ServerMapSaveFileNameProperty, value); }
}
public static readonly DependencyProperty ServerModIdsProperty = DependencyProperty.Register(nameof(ServerModIds), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
public string ServerModIds
{
get { return (string)GetValue(ServerModIdsProperty); }
set { SetValue(ServerModIdsProperty, value); }
}
public static readonly DependencyProperty RconEnabledProperty = DependencyProperty.Register(nameof(RconEnabled), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
[IniFileEntry(IniFiles.Game, IniSections.Game_RconPlugin, ServerProfileCategory.Administration, ConditionedOn = nameof(RconEnabled), WriteBooleanAsInteger = true)]
public bool RconEnabled
{
get { return (bool)GetValue(RconEnabledProperty); }
set { SetValue(RconEnabledProperty, value); }
}
public static readonly DependencyProperty RconPortProperty = DependencyProperty.Register(nameof(RconPort), typeof(int), typeof(ServerProfile), new PropertyMetadata(25575));
[DataMember]
[IniFileEntry(IniFiles.Game, IniSections.Game_RconPlugin, ServerProfileCategory.Administration, ConditionedOn = nameof(RconEnabled))]
public int RconPort
{
get { return (int)GetValue(RconPortProperty); }
set { SetValue(RconPortProperty, value); }
}
public static readonly DependencyProperty RconPasswordProperty = DependencyProperty.Register(nameof(RconPassword), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
[IniFileEntry(IniFiles.Game, IniSections.Game_RconPlugin, ServerProfileCategory.Administration, ConditionedOn = nameof(RconEnabled))]
public string RconPassword
{
get { return (string)GetValue(RconPasswordProperty); }
set { SetValue(RconPasswordProperty, value); }
}
public static readonly DependencyProperty MOTDProperty = DependencyProperty.Register(nameof(MOTD), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[IniFileEntry(IniFiles.ServerSettings, IniSections.ServerSettings_ServerSettings, ServerProfileCategory.Administration, "ServerMessageOfTheDay", Multiline = true, MultilineSeparator = "
", QuotedString = QuotedStringType.Remove)]
public string MOTD
{
get { return (string)GetValue(MOTDProperty); }
set
{
SetValue(MOTDProperty, value);
ValidateMOTD();
}
}
public static readonly DependencyProperty MOTDLineCountProperty = DependencyProperty.Register(nameof(MOTDLineCount), typeof(int), typeof(ServerProfile), new PropertyMetadata(0));
public int MOTDLineCount
{
get { return (int)GetValue(MOTDLineCountProperty); }
set { SetValue(MOTDLineCountProperty, value); }
}
public static readonly DependencyProperty MOTDLineCountToLongProperty = DependencyProperty.Register(nameof(MOTDLineCountToLong), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
public bool MOTDLineCountToLong
{
get { return (bool)GetValue(MOTDLineCountToLongProperty); }
set { SetValue(MOTDLineCountToLongProperty, value); }
}
public static readonly DependencyProperty MOTDLengthProperty = DependencyProperty.Register(nameof(MOTDLength), typeof(int), typeof(ServerProfile), new PropertyMetadata(0));
public int MOTDLength
{
get { return (int)GetValue(MOTDLengthProperty); }
set { SetValue(MOTDLengthProperty, value); }
}
public static readonly DependencyProperty MOTDLengthToLongProperty = DependencyProperty.Register(nameof(MOTDLengthToLong), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
public bool MOTDLengthToLong
{
get { return (bool)GetValue(MOTDLengthToLongProperty); }
set { SetValue(MOTDLengthToLongProperty, value); }
}
public static readonly DependencyProperty MOTDIntervalEnabledProperty = DependencyProperty.Register(nameof(MOTDIntervalEnabled), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
public bool MOTDIntervalEnabled
{
get { return (bool)GetValue(MOTDIntervalEnabledProperty); }
set { SetValue(MOTDIntervalEnabledProperty, value); }
}
public static readonly DependencyProperty MOTDIntervalProperty = DependencyProperty.Register(nameof(MOTDInterval), typeof(int), typeof(ServerProfile), new PropertyMetadata(60));
[DataMember]
public int MOTDInterval
{
get { return (int)GetValue(MOTDIntervalProperty); }
set { SetValue(MOTDIntervalProperty, value); }
}
public static readonly DependencyProperty UseVACProperty = DependencyProperty.Register(nameof(UseVAC), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[IniFileEntry(IniFiles.ServerSettings, IniSections.ServerSettings_ServerSettings, ServerProfileCategory.Administration, "IsVACEnabled")]
public bool UseVAC
{
get { return (bool)GetValue(UseVACProperty); }
set { SetValue(UseVACProperty, value); }
}
public static readonly DependencyProperty UseBattlEyeProperty = DependencyProperty.Register(nameof(UseBattlEye), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[IniFileEntry(IniFiles.ServerSettings, IniSections.ServerSettings_ServerSettings, ServerProfileCategory.Administration, "IsBattlEyeEnabled")]
public bool UseBattlEye
{
get { return (bool)GetValue(UseBattlEyeProperty); }
set { SetValue(UseBattlEyeProperty, value); }
}
public static readonly DependencyProperty AllowFamilySharedAccountProperty = DependencyProperty.Register(nameof(AllowFamilySharedAccount), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[IniFileEntry(IniFiles.ServerSettings, IniSections.ServerSettings_ServerSettings, ServerProfileCategory.Administration)]
public bool AllowFamilySharedAccount
{
get { return (bool)GetValue(AllowFamilySharedAccountProperty); }
set { SetValue(AllowFamilySharedAccountProperty, value); }
}
public static readonly DependencyProperty ServerRegionProperty = DependencyProperty.Register(nameof(ServerRegion), typeof(string), typeof(ServerProfile), new PropertyMetadata("0"));
[IniFileEntry(IniFiles.ServerSettings, IniSections.ServerSettings_ServerSettings, ServerProfileCategory.Administration, QuotedString = QuotedStringType.Remove)]
public string ServerRegion
{
get { return (string)GetValue(ServerRegionProperty); }
set { SetValue(ServerRegionProperty, value); }
}
public static readonly DependencyProperty MaxPlayersProperty = DependencyProperty.Register(nameof(MaxPlayers), typeof(int), typeof(ServerProfile), new PropertyMetadata(70));
[IniFileEntry(IniFiles.Game, IniSections.Game_GameSession, ServerProfileCategory.Administration)]
public int MaxPlayers
{
get { return (int)GetValue(MaxPlayersProperty); }
set { SetValue(MaxPlayersProperty, value); }
}
public static readonly DependencyProperty KickIdlePlayersPercentageProperty = DependencyProperty.Register(nameof(KickIdlePlayersPercentage), typeof(int), typeof(ServerProfile), new PropertyMetadata(80));
[IniFileEntry(IniFiles.ServerSettings, IniSections.ServerSettings_ServerSettings, ServerProfileCategory.Administration, "KickAFKPercentage")]
public int KickIdlePlayersPercentage
{
get { return (int)GetValue(KickIdlePlayersPercentageProperty); }
set { SetValue(KickIdlePlayersPercentageProperty, value); }
}
public static readonly DependencyProperty KickIdlePlayersPeriodProperty = DependencyProperty.Register(nameof(KickIdlePlayersPeriod), typeof(int), typeof(ServerProfile), new PropertyMetadata(3600));
[IniFileEntry(IniFiles.ServerSettings, IniSections.ServerSettings_ServerSettings, ServerProfileCategory.Administration, "KickAFKTime")]
public int KickIdlePlayersPeriod
{
get { return (int)GetValue(KickIdlePlayersPeriodProperty); }
set { SetValue(KickIdlePlayersPeriodProperty, value); }
}
public static readonly DependencyProperty ServerTransferEnabledProperty = DependencyProperty.Register(nameof(ServerTransferEnabled), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[IniFileEntry(IniFiles.ServerSettings, IniSections.ServerSettings_ServerSettings, ServerProfileCategory.Administration)]
public bool ServerTransferEnabled
{
get { return (bool)GetValue(ServerTransferEnabledProperty); }
set { SetValue(ServerTransferEnabledProperty, value); }
}
public static readonly DependencyProperty CanImportDirectlyFromSameServerProperty = DependencyProperty.Register(nameof(CanImportDirectlyFromSameServer), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[IniFileEntry(IniFiles.ServerSettings, IniSections.ServerSettings_ServerSettings, ServerProfileCategory.Administration)]
public bool CanImportDirectlyFromSameServer
{
get { return (bool)GetValue(CanImportDirectlyFromSameServerProperty); }
set { SetValue(CanImportDirectlyFromSameServerProperty, value); }
}
public static readonly DependencyProperty BranchNameProperty = DependencyProperty.Register(nameof(BranchName), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
public string BranchName
{
get { return (string)GetValue(BranchNameProperty); }
set { SetValue(BranchNameProperty, value); }
}
public static readonly DependencyProperty BranchPasswordProperty = DependencyProperty.Register(nameof(BranchPassword), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
public string BranchPassword
{
get { return (string)GetValue(BranchPasswordProperty); }
set { SetValue(BranchPasswordProperty, value); }
}
public static readonly DependencyProperty ProcessPriorityProperty = DependencyProperty.Register(nameof(ProcessPriority), typeof(string), typeof(ServerProfile), new PropertyMetadata("normal"));
[DataMember]
public string ProcessPriority
{
get { return (string)GetValue(ProcessPriorityProperty); }
set { SetValue(ProcessPriorityProperty, value); }
}
public static readonly DependencyProperty ProcessAffinityProperty = DependencyProperty.Register(nameof(ProcessAffinity), typeof(BigInteger), typeof(ServerProfile), new PropertyMetadata(BigInteger.Zero));
[DataMember]
public BigInteger ProcessAffinity
{
get { return (BigInteger)GetValue(ProcessAffinityProperty); }
set { SetValue(ProcessAffinityProperty, value); }
}
public static readonly DependencyProperty AdditionalArgsProperty = DependencyProperty.Register(nameof(AdditionalArgs), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
public string AdditionalArgs
{
get { return (string)GetValue(AdditionalArgsProperty); }
set { SetValue(AdditionalArgsProperty, value); }
}
public static readonly DependencyProperty LauncherArgsOverrideProperty = DependencyProperty.Register(nameof(LauncherArgsOverride), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
public bool LauncherArgsOverride
{
get { return (bool)GetValue(LauncherArgsOverrideProperty); }
set { SetValue(LauncherArgsOverrideProperty, value); }
}
public static readonly DependencyProperty LauncherArgsProperty = DependencyProperty.Register(nameof(LauncherArgs), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
public string LauncherArgs
{
get { return (string)GetValue(LauncherArgsProperty); }
set { SetValue(LauncherArgsProperty, value); }
}
#endregion
#region Automatic Management
public static readonly DependencyProperty EnableAutoBackupProperty = DependencyProperty.Register(nameof(EnableAutoBackup), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
public bool EnableAutoBackup
{
get { return (bool)GetValue(EnableAutoBackupProperty); }
set { SetValue(EnableAutoBackupProperty, value); }
}
public static readonly DependencyProperty EnableAutoStartProperty = DependencyProperty.Register(nameof(EnableAutoStart), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
public bool EnableAutoStart
{
get { return (bool)GetValue(EnableAutoStartProperty); }
set { SetValue(EnableAutoStartProperty, value); }
}
public static readonly DependencyProperty EnableAutoUpdateProperty = DependencyProperty.Register(nameof(EnableAutoUpdate), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
public bool EnableAutoUpdate
{
get { return (bool)GetValue(EnableAutoUpdateProperty); }
set { SetValue(EnableAutoUpdateProperty, value); }
}
public static readonly DependencyProperty EnableAutoShutdown1Property = DependencyProperty.Register(nameof(EnableAutoShutdown1), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
public bool EnableAutoShutdown1
{
get { return (bool)GetValue(EnableAutoShutdown1Property); }
set { SetValue(EnableAutoShutdown1Property, value); }
}
public static readonly DependencyProperty AutoShutdownTime1Property = DependencyProperty.Register(nameof(AutoShutdownTime1), typeof(string), typeof(ServerProfile), new PropertyMetadata("00:00"));
[DataMember]
public string AutoShutdownTime1
{
get { return (string)GetValue(AutoShutdownTime1Property); }
set { SetValue(AutoShutdownTime1Property, value); }
}
public static readonly DependencyProperty ShutdownDaysOfTheWeek1Property = DependencyProperty.Register(nameof(ShutdownDaysOfTheWeek1), typeof(DaysOfTheWeek), typeof(ServerProfile), new PropertyMetadata(DaysOfTheWeek.AllDays));
[DataMember]
public DaysOfTheWeek ShutdownDaysOfTheWeek1
{
get { return (DaysOfTheWeek)GetValue(ShutdownDaysOfTheWeek1Property); }
set { SetValue(ShutdownDaysOfTheWeek1Property, value); }
}
public static readonly DependencyProperty RestartAfterShutdown1Property = DependencyProperty.Register(nameof(RestartAfterShutdown1), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[DataMember]
public bool RestartAfterShutdown1
{
get { return (bool)GetValue(RestartAfterShutdown1Property); }
set { SetValue(RestartAfterShutdown1Property, value); }
}
public static readonly DependencyProperty UpdateAfterShutdown1Property = DependencyProperty.Register(nameof(UpdateAfterShutdown1), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
public bool UpdateAfterShutdown1
{
get { return (bool)GetValue(UpdateAfterShutdown1Property); }
set { SetValue(UpdateAfterShutdown1Property, value); }
}
public static readonly DependencyProperty EnableAutoShutdown2Property = DependencyProperty.Register(nameof(EnableAutoShutdown2), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
public bool EnableAutoShutdown2
{
get { return (bool)GetValue(EnableAutoShutdown2Property); }
set { SetValue(EnableAutoShutdown2Property, value); }
}
public static readonly DependencyProperty AutoShutdownTime2Property = DependencyProperty.Register(nameof(AutoShutdownTime2), typeof(string), typeof(ServerProfile), new PropertyMetadata("00:00"));
[DataMember]
public string AutoShutdownTime2
{
get { return (string)GetValue(AutoShutdownTime2Property); }
set { SetValue(AutoShutdownTime2Property, value); }
}
public static readonly DependencyProperty ShutdownDaysOfTheWeek2Property = DependencyProperty.Register(nameof(ShutdownDaysOfTheWeek2), typeof(DaysOfTheWeek), typeof(ServerProfile), new PropertyMetadata(DaysOfTheWeek.AllDays));
[DataMember]
public DaysOfTheWeek ShutdownDaysOfTheWeek2
{
get { return (DaysOfTheWeek)GetValue(ShutdownDaysOfTheWeek2Property); }
set { SetValue(ShutdownDaysOfTheWeek2Property, value); }
}
public static readonly DependencyProperty RestartAfterShutdown2Property = DependencyProperty.Register(nameof(RestartAfterShutdown2), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[DataMember]
public bool RestartAfterShutdown2
{
get { return (bool)GetValue(RestartAfterShutdown2Property); }
set { SetValue(RestartAfterShutdown2Property, value); }
}
public static readonly DependencyProperty UpdateAfterShutdown2Property = DependencyProperty.Register(nameof(UpdateAfterShutdown2), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
public bool UpdateAfterShutdown2
{
get { return (bool)GetValue(UpdateAfterShutdown2Property); }
set { SetValue(UpdateAfterShutdown2Property, value); }
}
public static readonly DependencyProperty AutoRestartIfShutdownProperty = DependencyProperty.Register(nameof(AutoRestartIfShutdown), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
public bool AutoRestartIfShutdown
{
get { return (bool)GetValue(AutoRestartIfShutdownProperty); }
set { SetValue(AutoRestartIfShutdownProperty, value); }
}
#endregion
#region Discord Bot
public static readonly DependencyProperty DiscordChannelIdProperty = DependencyProperty.Register(nameof(DiscordChannelId), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
public string DiscordChannelId
{
get { return (string)GetValue(DiscordChannelIdProperty); }
set { SetValue(DiscordChannelIdProperty, value); }
}
public static readonly DependencyProperty DiscordAliasProperty = DependencyProperty.Register(nameof(DiscordAlias), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
public string DiscordAlias
{
get { return (string)GetValue(DiscordAliasProperty); }
set { SetValue(DiscordAliasProperty, value); }
}
public static readonly DependencyProperty AllowDiscordBackupProperty = DependencyProperty.Register(nameof(AllowDiscordBackup), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[DataMember]
public bool AllowDiscordBackup
{
get { return (bool)GetValue(AllowDiscordBackupProperty); }
set { SetValue(AllowDiscordBackupProperty, value); }
}
public static readonly DependencyProperty AllowDiscordRestartProperty = DependencyProperty.Register(nameof(AllowDiscordRestart), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[DataMember]
public bool AllowDiscordRestart
{
get { return (bool)GetValue(AllowDiscordRestartProperty); }
set { SetValue(AllowDiscordRestartProperty, value); }
}
public static readonly DependencyProperty AllowDiscordShutdownProperty = DependencyProperty.Register(nameof(AllowDiscordShutdown), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[DataMember]
public bool AllowDiscordShutdown
{
get { return (bool)GetValue(AllowDiscordShutdownProperty); }
set { SetValue(AllowDiscordShutdownProperty, value); }
}
public static readonly DependencyProperty AllowDiscordStartProperty = DependencyProperty.Register(nameof(AllowDiscordStart), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[DataMember]
public bool AllowDiscordStart
{
get { return (bool)GetValue(AllowDiscordStartProperty); }
set { SetValue(AllowDiscordStartProperty, value); }
}
public static readonly DependencyProperty AllowDiscordStopProperty = DependencyProperty.Register(nameof(AllowDiscordStop), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[DataMember]
public bool AllowDiscordStop
{
get { return (bool)GetValue(AllowDiscordStopProperty); }
set { SetValue(AllowDiscordStopProperty, value); }
}
public static readonly DependencyProperty AllowDiscordUpdateProperty = DependencyProperty.Register(nameof(AllowDiscordUpdate), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[DataMember]
public bool AllowDiscordUpdate
{
get { return (bool)GetValue(AllowDiscordUpdateProperty); }
set { SetValue(AllowDiscordUpdateProperty, value); }
}
#endregion
#region Server Files
public static readonly DependencyProperty ServerFilesBlacklistedProperty = DependencyProperty.Register(nameof(ServerFilesBlacklisted), typeof(PlayerUserList), typeof(ServerProfile), new PropertyMetadata(null));
[DataMember]
public PlayerUserList ServerFilesBlacklisted
{
get { return (PlayerUserList)GetValue(ServerFilesBlacklistedProperty); }
set { SetValue(ServerFilesBlacklistedProperty, value); }
}
public static readonly DependencyProperty EnableWhitelistProperty = DependencyProperty.Register(nameof(EnableWhitelist), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[IniFileEntry(IniFiles.ServerSettings, IniSections.ServerSettings_ServerSettings, ServerProfileCategory.ServerFiles)]
public bool EnableWhitelist
{
get { return (bool)GetValue(EnableWhitelistProperty); }
set { SetValue(EnableWhitelistProperty, value); }
}
public static readonly DependencyProperty ServerFilesWhitelistedProperty = DependencyProperty.Register(nameof(ServerFilesWhitelisted), typeof(PlayerUserList), typeof(ServerProfile), new PropertyMetadata(null));
[DataMember]
public PlayerUserList ServerFilesWhitelisted
{
get { return (PlayerUserList)GetValue(ServerFilesWhitelistedProperty); }
set { SetValue(ServerFilesWhitelistedProperty, value); }
}
#endregion
#region RCON
public static readonly DependencyProperty RconWindowExtentsProperty = DependencyProperty.Register(nameof(RconWindowExtents), typeof(Rect), typeof(ServerProfile), new PropertyMetadata(new Rect(0f, 0f, 0f, 0f)));
[DataMember]
public Rect RconWindowExtents
{
get { return (Rect)GetValue(RconWindowExtentsProperty); }
set { SetValue(RconWindowExtentsProperty, value); }
}
public static readonly DependencyProperty RconPlayerListWidthProperty = DependencyProperty.Register(nameof(RconPlayerListWidth), typeof(double), typeof(ServerProfile), new PropertyMetadata(200d));
[DataMember]
public double RconPlayerListWidth
{
get { return (double)GetValue(RconPlayerListWidthProperty); }
set { SetValue(RconPlayerListWidthProperty, value); }
}
#endregion
#region Player List
public static readonly DependencyProperty PlayerListWindowExtentsProperty = DependencyProperty.Register(nameof(PlayerListWindowExtents), typeof(Rect), typeof(ServerProfile), new PropertyMetadata(new Rect(0f, 0f, 0f, 0f)));
[DataMember]
public Rect PlayerListWindowExtents
{
get { return (Rect)GetValue(PlayerListWindowExtentsProperty); }
set { SetValue(PlayerListWindowExtentsProperty, value); }
}
#endregion
#endregion
#region Methods
#region Common Methods
public void ChangeInstallationFolder(string folder)
{
InstallDirectory = folder;
LoadServerFiles(true, true);
SetupServerFilesWatcher();
}
private void CheckLauncherArgs()
{
// do not process if overriding the launcher args
if (this.LauncherArgsOverride)
return;
var launcherArgs = LauncherArgs?.ToLower() ?? string.Empty;
// check Launcher Args for priority
var priorityValues = ProcessUtils.GetProcessPriorityList();
foreach (var priority in priorityValues)
{
var priorityArg = $"/{priority}";
if (launcherArgs.Contains(priorityArg))
{
launcherArgs = launcherArgs.Replace(priorityArg, "");
ProcessPriority = priority;
}
}
LauncherArgs = launcherArgs;
if (string.IsNullOrWhiteSpace(LauncherArgs))
{
LauncherArgs = string.Empty;
// check if the launcher args override is enabled, but nothing has been defined in the launcher args
if (LauncherArgsOverride)
LauncherArgsOverride = false;
}
}
public void ClearSteamAppManifestBranch()
{
if (!string.IsNullOrWhiteSpace(BranchName))
return;
try
{
var manifestFile = ModUtils.GetSteamManifestFile(InstallDirectory);
if (string.IsNullOrWhiteSpace(manifestFile) || !File.Exists(manifestFile))
return;
// load the manifest files
var vdfDeserializer = VdfDeserializer.FromFile(manifestFile);
var vdf = vdfDeserializer.Deserialize();
// clear any of th beta keys values
var updated = SteamCmdManifestDetailsResult.ClearUserConfigBetaKeys(vdf);
// save the manifest file
if (updated)
{
var vdfSerializer = new VdfSerializer(vdf);
vdfSerializer.Serialize(manifestFile);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_BranchClearErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
}
}
internal static ServerProfile FromDefaults()
{
var settings = new ServerProfile();
settings.LoadServerFiles(true, true);
settings.SetupServerFilesWatcher();
return settings;
}
private void GetDefaultDirectories()
{
if (!string.IsNullOrWhiteSpace(InstallDirectory))
return;
// get the root servers folder
var installDirectory = Path.IsPathRooted(Config.Default.ServersInstallPath)
? Path.Combine(Config.Default.ServersInstallPath)
: Path.Combine(Config.Default.DataPath, Config.Default.ServersInstallPath);
var index = 1;
while (true)
{
// create a test profile folder name
var profileFolder = $"{Config.Default.DefaultServerRelativePath}{index}";
// get the test profile directory
var profileDirectory = Path.Combine(installDirectory, profileFolder);
// check if the profile directory exists
if (!Directory.Exists(profileDirectory))
{
// profile directory does not exist, assign the test profile directory to the profile
InstallDirectory = profileDirectory;
break;
}
index++;
}
}
private static IEnumerable GetExclusions()
{
return new List();
}
public string GetLauncherFile() => Path.Combine(GetProfileServerConfigDir(), Config.Default.LauncherFile);
[Obsolete("This method will be removed in a future version.")]
public string GetProfileConfigDir_Old() => Path.Combine(Path.GetDirectoryName(GetProfileFile()), this.ProfileName);
public string GetProfileFile() => Path.Combine(Config.Default.ConfigPath, Path.ChangeExtension(this.ProfileID.ToLower(), Config.Default.ProfileExtension));
public string GetProfileKey() => TaskSchedulerUtils.ComputeKey(this.InstallDirectory);
public string GetProfileServerConfigDir() => GetProfileServerConfigDir(this);
public static string GetProfileServerConfigDir(ServerProfile profile) => Path.Combine(profile.InstallDirectory, Config.Default.ServerConfigRelativePath);
public string GetServerAppId()
{
try
{
var appFile = Path.Combine(InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ServerAppIdFile);
return File.Exists(appFile) ? File.ReadAllText(appFile).Trim() : string.Empty;
}
catch
{
return string.Empty;
}
}
public string GetServerArgs()
{
var serverArgs = new StringBuilder();
serverArgs.Append(GetProfileMapName(this));
if (!string.IsNullOrWhiteSpace(this.ServerIP))
{
serverArgs.Append(" ");
serverArgs.AppendFormat(Config.Default.ServerCommandLineArgsIPMatchFormat, this.ServerIP);
}
serverArgs.Append($" -Port={this.ServerPort}");
serverArgs.Append(" ");
serverArgs.AppendFormat(Config.Default.ServerCommandLineArgsPortMatchFormat, this.QueryPort);
if (this.RconEnabled)
{
serverArgs.AppendFormat($" -RconPort={this.RconPort}");
}
if (!string.IsNullOrWhiteSpace(this.AdditionalArgs))
{
serverArgs.Append($" {this.AdditionalArgs.Trim()}");
}
serverArgs.Append(" ");
serverArgs.Append(Config.Default.ServerCommandLineStandardArgs);
return serverArgs.ToString();
}
public string GetServerExeFile() => Path.Combine(this.InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ServerExeFile);
public string GetServerSavedFilePath() => Path.Combine(this.InstallDirectory, Config.Default.SavedFilesRelativePath);
public string GetServerWorldFile()
{
var saveFolder = GetServerSavedFilePath();
return IOUtils.NormalizePath(Path.Combine(saveFolder, ServerMapSaveFileName));
}
public static ServerProfile LoadFrom(string file, ServerProfile profile = null)
{
if (string.IsNullOrWhiteSpace(file) || !File.Exists(file))
return null;
if (Path.GetExtension(file) == Config.Default.ProfileExtension)
return LoadFromProfileFile(file, profile);
var filePath = Path.GetDirectoryName(file);
profile = LoadFromConfigFiles(file, profile);
if (filePath.EndsWith(Config.Default.ServerConfigRelativePath))
{
var installDirectory = filePath.Replace(Config.Default.ServerConfigRelativePath, string.Empty).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
profile.ChangeInstallationFolder(installDirectory);
}
return profile;
}
public static ServerProfile LoadFromConfigFiles(string file, ServerProfile profile, IEnumerable exclusions = null)
{
if (string.IsNullOrWhiteSpace(file) || !File.Exists(file))
return null;
if (exclusions == null)
exclusions = GetExclusions();
var iniPath = Path.GetDirectoryName(file);
var iniFile = new SystemIniFile(iniPath);
profile = profile ?? new ServerProfile();
iniFile.Deserialize(profile, exclusions);
return profile;
}
public static ServerProfile LoadFromProfileFile(string file, ServerProfile profile)
{
if (string.IsNullOrWhiteSpace(file) || !File.Exists(file))
return null;
if (Path.GetExtension(file) != Config.Default.ProfileExtension)
return null;
profile = profile ?? new ServerProfile();
try
{
var settings = new JsonSerializerSettings();
settings.Converters.Add(new NullableValueConverter());
settings.Converters.Add(new NullableValueConverter());
profile = JsonUtils.DeserializeFromFile(file, settings);
if (profile == null)
return null;
}
catch
{
// could not load the profile file, just exit
return null;
}
// check if profile id and filename match
var fileName = Path.GetFileNameWithoutExtension(file);
if (Guid.TryParse(fileName, out Guid fileId) && Guid.TryParse(profile.ProfileID, out Guid profileId))
{
// filename is a guid - check it against the profile id
if (!Guid.Equals(fileId, profileId))
{
// id values are not in sync, change the profile id to be the same as the filename
profile.ProfileID = fileId.ToString();
}
}
profile.CheckLauncherArgs();
var serverConfigFile = Path.Combine(GetProfileServerConfigDir(profile), Config.Default.ServerGameConfigFile);
if (File.Exists(serverConfigFile))
{
profile = LoadFromConfigFiles(serverConfigFile, profile);
}
profile.LoadServerFiles(true, true);
profile.SetupServerFilesWatcher();
profile._lastSaveLocation = file;
return profile;
}
public void Save(bool updateFolderPermissions, bool updateSchedules, ProgressDelegate progressCallback)
{
if (string.IsNullOrWhiteSpace(Config.Default.DataPath))
return;
progressCallback?.Invoke(0, _globalizer.GetResourceString("ProfileSave_Saving"));
UpdateProfileToolTip();
ClearSteamAppManifestBranch();
CheckLauncherArgs();
// check if the processor affinity is valid
if (!ProcessUtils.IsProcessorAffinityValid(ProcessAffinity))
// processor affinity is not valid, set back to 0 (default ALL processors)
ProcessAffinity = 0;
//
// Save the profile
//
progressCallback?.Invoke(0, _globalizer.GetResourceString("ProfileSave_SavingProfileFile"));
SaveProfile();
try
{
DestroyServerFilesWatcher();
SaveServerFileBlacklisted();
SaveServerFileWhitelisted();
}
finally
{
SetupServerFilesWatcher();
}
//
// Write the config files
//
progressCallback?.Invoke(0, _globalizer.GetResourceString("ProfileSave_SavingConfigFiles"));
SaveConfigFiles();
// update the modlist file
ModUtils.CreateModListFile(InstallDirectory, ModUtils.GetModIdList(ServerModIds));
//
// If this was a rename, remove the old profile after writing the new one.
//
if (!String.Equals(GetProfileFile(), this._lastSaveLocation, StringComparison.OrdinalIgnoreCase))
{
try
{
if (File.Exists(this._lastSaveLocation))
File.Delete(this._lastSaveLocation);
var profileFile = Path.ChangeExtension(this._lastSaveLocation, Config.Default.ProfileExtension);
if (File.Exists(profileFile))
File.Delete(profileFile);
var profileIniDir = Path.ChangeExtension(this._lastSaveLocation, null);
if (Directory.Exists(profileIniDir))
Directory.Delete(profileIniDir, true);
}
catch (IOException)
{
// We tried...
}
this._lastSaveLocation = GetProfileFile();
}
progressCallback?.Invoke(0, _globalizer.GetResourceString("ProfileSave_SavingLauncherFile"));
SaveLauncher();
if (updateFolderPermissions)
{
progressCallback?.Invoke(0, _globalizer.GetResourceString("ProfileSave_CheckingDirectoryPermissions"));
UpdateDirectoryPermissions();
}
if (updateSchedules)
{
progressCallback?.Invoke(0, _globalizer.GetResourceString("ProfileSave_CheckingScheduledTasks"));
UpdateSchedules();
}
}
public void SaveProfile()
{
//
// Save the profile
//
JsonUtils.SerializeToFile(this, GetProfileFile());
}
public void SaveLauncher()
{
var commandArgs = new StringBuilder();
if (this.LauncherArgsOverride)
{
commandArgs.Append(this.LauncherArgs);
}
else
{
var drive = Path.GetPathRoot(this.InstallDirectory);
drive = drive.Replace(Path.DirectorySeparatorChar.ToString(), string.Empty);
drive = drive.Replace(Path.AltDirectorySeparatorChar.ToString(), string.Empty);
commandArgs.Append("start");
commandArgs.Append($" \"{this.ProfileName}\"");
commandArgs.Append($" /{ProcessPriority}");
if (ProcessAffinity > 0 && ProcessUtils.IsProcessorAffinityValid(ProcessAffinity))
{
commandArgs.Append($" /affinity {ProcessAffinity.ToString("X")}");
}
if (!string.IsNullOrWhiteSpace(this.LauncherArgs))
{
commandArgs.Append($" {this.LauncherArgs.Trim()}");
}
commandArgs.Append($" \"{GetServerExeFile()}\"");
commandArgs.Append($" {GetServerArgs()}");
}
Directory.CreateDirectory(Path.GetDirectoryName(GetLauncherFile()));
File.WriteAllText(GetLauncherFile(), commandArgs.ToString());
}
public void SaveConfigFiles()
{
//
// Remove the old profile ini backups
//
var profileIniDir = GetProfileConfigDir_Old();
if (Directory.Exists(profileIniDir))
{
// set the folder permissions
SecurityUtils.SetDirectoryOwnershipForAllUsers(profileIniDir);
try
{
Directory.Delete(profileIniDir, true);
}
catch (Exception) { }
}
//
// Save to the installation location
//
string serverConfigDir = GetProfileServerConfigDir();
Directory.CreateDirectory(serverConfigDir);
SaveConfigFile(serverConfigDir);
}
public void SaveConfigFile(string configDir, IEnumerable exclusions = null)
{
if (exclusions == null)
exclusions = GetExclusions();
var iniFile = new SystemIniFile(configDir);
iniFile.Serialize(this, exclusions);
}
public bool UpdateDirectoryPermissions()
{
if (!SecurityUtils.IsAdministrator())
return true;
if (!SecurityUtils.SetDirectoryOwnershipForAllUsers(this.InstallDirectory))
{
Logger.Debug($"Unable to set directory permissions for {this.InstallDirectory}.");
return false;
}
return true;
}
public bool UpdateSchedules()
{
SaveLauncher();
if (!SecurityUtils.IsAdministrator())
return true;
var taskKey = GetProfileKey();
if(!TaskSchedulerUtils.ScheduleAutoStart(taskKey, null, this.EnableAutoStart, GetLauncherFile(), ProfileName, true))
{
return false;
}
TimeSpan shutdownTime;
var command = Assembly.GetEntryAssembly().Location;
if (!TaskSchedulerUtils.ScheduleAutoShutdown(taskKey, "#1", command, this.EnableAutoShutdown1 ? (TimeSpan.TryParseExact(this.AutoShutdownTime1, "g", null, out shutdownTime) ? shutdownTime : (TimeSpan?)null) : null, ShutdownDaysOfTheWeek1, ProfileName, TaskSchedulerUtils.ShutdownType.Shutdown1))
{
return false;
}
if (!TaskSchedulerUtils.ScheduleAutoShutdown(taskKey, "#2", command, this.EnableAutoShutdown2 ? (TimeSpan.TryParseExact(this.AutoShutdownTime2, "g", null, out shutdownTime) ? shutdownTime : (TimeSpan?)null) : null, ShutdownDaysOfTheWeek2, ProfileName, TaskSchedulerUtils.ShutdownType.Shutdown2))
{
return false;
}
return true;
}
public bool Validate(bool forceValidate, out string validationMessage)
{
validationMessage = string.Empty;
StringBuilder result = new StringBuilder();
var appId = Config.Default.AppId;
// checking the port values are within the valid range
if (ServerPort < ushort.MinValue || ServerPort > ushort.MaxValue)
{
var message = _globalizer.GetResourceString("ProfileValidation_ServerPort")?.Replace("{PortMinimum}", ushort.MinValue.ToString()).Replace("{PortMaximum}", ushort.MaxValue.ToString());
result.AppendLine(message);
}
if (ServerPeerPort < ushort.MinValue || ServerPeerPort > ushort.MaxValue)
{
var message = _globalizer.GetResourceString("ProfileValidation_ServerPeerPort")?.Replace("{PortMinimum}", ushort.MinValue.ToString()).Replace("{PortMaximum}", ushort.MaxValue.ToString());
result.AppendLine(message);
}
if (QueryPort < ushort.MinValue || QueryPort > ushort.MaxValue)
{
var message = _globalizer.GetResourceString("ProfileValidation_QueryPort")?.Replace("{PortMinimum}", ushort.MinValue.ToString()).Replace("{PortMaximum}", ushort.MaxValue.ToString());
result.AppendLine(message);
}
if (RconPort < ushort.MinValue || RconPort > ushort.MaxValue)
{
var message = _globalizer.GetResourceString("ProfileValidation_RconPort")?.Replace("{PortMinimum}", ushort.MinValue.ToString()).Replace("{PortMaximum}", ushort.MaxValue.ToString());
result.AppendLine(message);
}
if (forceValidate || Config.Default.ValidateProfileOnServerStart)
{
// build a list of mods to be processed
var modIds = ModUtils.GetModIdList(ServerModIds);
modIds = ModUtils.ValidateModList(modIds);
var modIdList = new List();
modIdList.AddRange(modIds);
modIdList = ModUtils.ValidateModList(modIdList);
var modDetails = SteamUtils.GetSteamModDetails(modIdList);
// check for map name.
if (string.IsNullOrWhiteSpace(ServerMap))
{
var message = _globalizer.GetResourceString("ProfileValidation_MapNameBlank");
result.AppendLine(message);
}
// check if the server executable exists
var serverFolder = Path.Combine(InstallDirectory, Config.Default.ServerBinaryRelativePath);
var serverFile = Path.Combine(serverFolder, Config.Default.ServerExeFile);
if (!Directory.Exists(serverFolder))
{
var message = _globalizer.GetResourceString("ProfileValidation_ServerNotDownloaded");
result.AppendLine(message);
}
else if (!File.Exists(serverFile))
{
var message = _globalizer.GetResourceString("ProfileValidation_ServerExeNotDownloaded")?.Replace("{ServerExe}", Config.Default.ServerExeFile);
result.AppendLine(message);
}
else
{
var serverAppId = GetServerAppId();
if (!serverAppId.Equals(appId))
{
var message = _globalizer.GetResourceString("ProfileValidation_ServerDifferentApplication");
result.AppendLine(message);
}
}
// check for the mods
foreach (var modId in modIds)
{
var modFilename = $"{modId}.pak";
var modFile = IOUtils.NormalizePath(Path.Combine(ModUtils.GetModRootPath(InstallDirectory), modFilename));
if (!File.Exists(modFile))
{
var message = _globalizer.GetResourceString("ProfileValidation_ModFileNotDownloaded")?.Replace("{modId}", modId);
result.AppendLine(message);
}
else
{
var modDetail = modDetails?.publishedfiledetails?.FirstOrDefault(d => d.publishedfileid.Equals(modId));
if (modDetail != null && modDetail.consumer_app_id != null)
{
if (!modDetail.consumer_app_id.Equals(appId))
{
var message = _globalizer.GetResourceString("ProfileValidation_ModDifferentApplication")?.Replace("modId", modId);
result.AppendLine(message);
}
else
{
var modVersion = ModUtils.GetModLatestTime(ModUtils.GetLatestModTimeFile(InstallDirectory, modId));
if (modVersion == 0 || !modVersion.Equals(modDetail.time_updated))
{
var message = _globalizer.GetResourceString("ProfileValidation_ModOutdated")?.Replace("{modId}", modId);
result.AppendLine(message);
}
}
}
else
{
var message = _globalizer.GetResourceString("ProfileValidation_ModSteamError")?.Replace("{modId}", modId);
result.AppendLine(message);
}
}
}
}
validationMessage = result.ToString();
return string.IsNullOrWhiteSpace(validationMessage);
}
public string ToOutputString()
{
//
// serializes the profile to a string
//
return JsonUtils.Serialize(this);
}
public int RestoreSaveFiles(string restoreFile, bool isArchiveFile)
{
if (string.IsNullOrWhiteSpace(restoreFile) || !File.Exists(restoreFile))
{
var message = _globalizer.GetResourceString("RestoreSaveFiles_BackupFileNotFound");
throw new FileNotFoundException(message, restoreFile);
}
var saveFolder = GetProfileSavePath(this);
if (!Directory.Exists(saveFolder))
{
var message = _globalizer.GetResourceString("RestoreSaveFiles_SaveFolderNotFound")?.Replace("{saveFolder}", saveFolder);
throw new DirectoryNotFoundException(message);
}
var worldFileName = ServerMapSaveFileName;
// check if the archive file contains the world save file at minimum
if (isArchiveFile)
{
if (!ZipUtils.DoesFileExist(restoreFile, worldFileName))
{
var message = _globalizer.GetResourceString("RestoreSaveFiles_MissingWorldSaveFile");
throw new Exception(message);
}
}
// create a backup of the existing save folder
var app = new ServerApp(true)
{
BackupWorldFile = false,
DeleteOldBackupFiles = false,
SendAlerts = false,
SendEmails = false,
OutputLogs = false
};
app.CreateServerBackupArchiveFile(null, ServerProfileSnapshot.Create(this));
var worldFile = IOUtils.NormalizePath(Path.Combine(saveFolder, worldFileName));
var restoreFileInfo = new FileInfo(restoreFile);
var restoredFileCount = 0;
if (isArchiveFile)
{
// create a list of files to be deleted
var files = new List();
// add the current world save file
files.Add(worldFile);
// add the world save support files
files.AddRange(Directory.GetFiles(saveFolder, $"{worldFileName}-*"));
// delete the selected files
foreach (var file in files)
{
try
{
File.Delete(file);
}
catch
{
// if unable to delete, do not bother
}
}
// restore the files from the backup
restoredFileCount = ZipUtils.ExtractAFile(restoreFile, worldFileName, saveFolder);
}
else
{
// copy the selected file
File.Copy(restoreFile, worldFile, true);
File.SetCreationTime(worldFile, restoreFileInfo.CreationTime);
File.SetLastWriteTime(worldFile, restoreFileInfo.LastWriteTime);
File.SetLastAccessTime(worldFile, restoreFileInfo.LastAccessTime);
restoredFileCount = 1;
}
return restoredFileCount;
}
public void UpdateProfileToolTip()
{
ProfileToolTip = $"{ProfileName ?? string.Empty} ({ProfileID ?? string.Empty})";
}
public void ValidateServerName()
{
ServerNameLength = Encoding.UTF8.GetByteCount(ServerName);
ServerNameLengthToLong = ServerNameLength > 48;
}
public void ValidateMOTD()
{
MOTDLength = Encoding.UTF8.GetByteCount(MOTD);
MOTDLengthToLong = MOTDLength > 200;
MOTDLineCount = string.IsNullOrWhiteSpace(MOTD) ? 0 : MOTD.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).Length;
MOTDLineCountToLong = MOTDLineCount > 5;
}
#endregion
#region Reset Methods
public void ResetProfileId()
{
this.ProfileID = Guid.NewGuid().ToString();
}
public void ResetRconWindowExtents()
{
this.ClearValue(RconWindowExtentsProperty);
}
public void ResetServerOptions()
{
this.ClearValue(UseVACProperty);
this.ClearValue(UseBattlEyeProperty);
this.ClearValue(AllowFamilySharedAccountProperty);
this.ClearValue(ServerRegionProperty);
this.ClearValue(MaxPlayersProperty);
this.ClearValue(KickIdlePlayersPercentageProperty);
this.ClearValue(KickIdlePlayersPeriodProperty);
}
// section reset methods
public void ResetAdministrationSection()
{
this.ClearValue(ServerNameProperty);
this.ClearValue(ServerPasswordProperty);
this.ClearValue(AdminPasswordProperty);
this.ClearValue(ServerIPProperty);
this.ClearValue(ServerPortProperty);
this.ClearValue(ServerPeerPortProperty);
this.ClearValue(QueryPortProperty);
this.ClearValue(ServerMapProperty);
this.ClearValue(ServerMapSaveFileNameProperty);
this.ClearValue(ServerModIdsProperty);
this.ClearValue(RconEnabledProperty);
this.ClearValue(RconPortProperty);
this.ClearValue(RconPasswordProperty);
this.ClearValue(MOTDProperty);
this.ClearValue(MOTDIntervalEnabledProperty);
this.ClearValue(MOTDIntervalProperty);
ResetServerOptions();
this.ClearValue(BranchNameProperty);
this.ClearValue(BranchPasswordProperty);
this.ClearValue(ProcessPriorityProperty);
this.ClearValue(ProcessAffinityProperty);
this.ClearValue(LauncherArgsOverrideProperty);
this.ClearValue(LauncherArgsProperty);
this.ClearValue(AdditionalArgsProperty);
}
public void ResetDiscordBotSection()
{
this.ClearValue(DiscordChannelIdProperty);
this.ClearValue(DiscordAliasProperty);
this.ClearValue(AllowDiscordBackupProperty);
this.ClearValue(AllowDiscordRestartProperty);
this.ClearValue(AllowDiscordShutdownProperty);
this.ClearValue(AllowDiscordStartProperty);
this.ClearValue(AllowDiscordStopProperty);
this.ClearValue(AllowDiscordUpdateProperty);
}
#endregion
#region Sync Methods
public void SyncSettings(ServerProfileCategory category, ServerProfile sourceProfile)
{
if (sourceProfile == null)
return;
switch (category)
{
case ServerProfileCategory.Administration:
SyncAdministrationSection(sourceProfile);
break;
case ServerProfileCategory.AutomaticManagement:
SyncAutomaticManagement(sourceProfile);
break;
case ServerProfileCategory.DiscordBot:
SyncDiscordBot(sourceProfile);
break;
case ServerProfileCategory.ServerFiles:
SyncServerFiles(sourceProfile);
break;
}
}
private void SyncAdministrationSection(ServerProfile sourceProfile)
{
this.SetValue(ServerModIdsProperty, sourceProfile.ServerModIds);
this.SetValue(MOTDProperty, sourceProfile.MOTD);
this.SetValue(MOTDIntervalEnabledProperty, sourceProfile.MOTDIntervalEnabled);
this.SetValue(MOTDIntervalProperty, sourceProfile.MOTDInterval);
this.SetValue(UseVACProperty, sourceProfile.UseVAC);
this.SetValue(UseBattlEyeProperty, sourceProfile.UseBattlEye);
this.SetValue(AllowFamilySharedAccountProperty, sourceProfile.AllowFamilySharedAccount);
this.SetValue(ServerRegionProperty, sourceProfile.ServerRegion);
this.SetValue(MaxPlayersProperty, sourceProfile.MaxPlayers);
this.SetValue(KickIdlePlayersPercentageProperty, sourceProfile.KickIdlePlayersPercentage);
this.SetValue(KickIdlePlayersPeriodProperty, sourceProfile.KickIdlePlayersPeriod);
this.SetValue(BranchNameProperty, sourceProfile.BranchName);
this.SetValue(BranchPasswordProperty, sourceProfile.BranchPassword);
this.SetValue(LauncherArgsOverrideProperty, sourceProfile.LauncherArgsOverride);
this.SetValue(LauncherArgsProperty, sourceProfile.LauncherArgs);
this.SetValue(AdditionalArgsProperty, sourceProfile.AdditionalArgs);
}
private void SyncAutomaticManagement(ServerProfile sourceProfile)
{
this.SetValue(EnableAutoBackupProperty, sourceProfile.EnableAutoBackup);
this.SetValue(EnableAutoStartProperty, sourceProfile.EnableAutoStart);
this.SetValue(EnableAutoUpdateProperty, sourceProfile.EnableAutoUpdate);
this.SetValue(EnableAutoShutdown1Property, sourceProfile.EnableAutoShutdown1);
this.SetValue(AutoShutdownTime1Property, sourceProfile.AutoShutdownTime1);
this.SetValue(ShutdownDaysOfTheWeek1Property, sourceProfile.ShutdownDaysOfTheWeek1);
this.SetValue(RestartAfterShutdown1Property, sourceProfile.RestartAfterShutdown1);
this.SetValue(UpdateAfterShutdown1Property, sourceProfile.UpdateAfterShutdown1);
this.SetValue(EnableAutoShutdown2Property, sourceProfile.EnableAutoShutdown2);
this.SetValue(AutoShutdownTime2Property, sourceProfile.AutoShutdownTime2);
this.SetValue(ShutdownDaysOfTheWeek2Property, sourceProfile.ShutdownDaysOfTheWeek2);
this.SetValue(RestartAfterShutdown2Property, sourceProfile.RestartAfterShutdown2);
this.SetValue(UpdateAfterShutdown2Property, sourceProfile.UpdateAfterShutdown2);
this.SetValue(AutoRestartIfShutdownProperty, sourceProfile.AutoRestartIfShutdown);
}
private void SyncDiscordBot(ServerProfile sourceProfile)
{
this.SetValue(DiscordChannelIdProperty, sourceProfile.DiscordChannelId);
this.SetValue(DiscordAliasProperty, sourceProfile.DiscordAlias);
this.SetValue(AllowDiscordBackupProperty, sourceProfile.AllowDiscordBackup);
this.SetValue(AllowDiscordRestartProperty, sourceProfile.AllowDiscordRestart);
this.SetValue(AllowDiscordShutdownProperty, sourceProfile.AllowDiscordShutdown);
this.SetValue(AllowDiscordStartProperty, sourceProfile.AllowDiscordStart);
this.SetValue(AllowDiscordStopProperty, sourceProfile.AllowDiscordStop);
this.SetValue(AllowDiscordUpdateProperty, sourceProfile.AllowDiscordUpdate);
}
private void SyncServerFiles(ServerProfile sourceProfile)
{
this.SetValue(ServerFilesBlacklistedProperty, sourceProfile.ServerFilesBlacklisted);
this.SetValue(EnableWhitelistProperty, sourceProfile.EnableWhitelist);
this.SetValue(ServerFilesWhitelistedProperty, sourceProfile.ServerFilesWhitelisted);
SaveServerFileBlacklisted();
SaveServerFileWhitelisted();
}
public void SyncMapSaveFileName()
{
var mapSaveFileName = GameData.MapSaveNameForClass(ServerMap, true);
if (!string.IsNullOrWhiteSpace(mapSaveFileName))
{
this.ServerMapSaveFileName = mapSaveFileName;
}
}
#endregion
#region Server Files
private void ServerFilesWatcher_Changed(object sender, FileSystemEventArgs e)
{
var blacklistFile = false;
var whitelistFile = false;
if (e.Name.Equals(Config.Default.ServerBlacklistFile, StringComparison.OrdinalIgnoreCase))
{
blacklistFile = true;
}
if (e.Name.Equals(Config.Default.ServerWhitelistFile, StringComparison.OrdinalIgnoreCase))
{
whitelistFile = true;
}
TaskUtils.RunOnUIThreadAsync(() => LoadServerFiles(blacklistFile, whitelistFile)).DoNotWait();
}
private void ServerFilesWatcher_Error(object sender, ErrorEventArgs e)
{
TaskUtils.RunOnUIThreadAsync(() => SetupServerFilesWatcher()).DoNotWait();
}
public void DestroyServerFilesWatcher()
{
if (_serverFilesWatcher == null)
return;
_serverFilesWatcher.EnableRaisingEvents = false;
_serverFilesWatcher.Changed -= ServerFilesWatcher_Changed;
_serverFilesWatcher.Created -= ServerFilesWatcher_Changed;
_serverFilesWatcher.Deleted -= ServerFilesWatcher_Changed;
_serverFilesWatcher.Error -= ServerFilesWatcher_Error;
_serverFilesWatcher = null;
}
public void SetupServerFilesWatcher()
{
if (_serverFilesWatcher != null)
DestroyServerFilesWatcher();
if (!EnableServerFilesWatcher)
return;
var path = GetServerSavedFilePath();
if (string.IsNullOrWhiteSpace(path) || !Directory.Exists(path))
return;
_serverFilesWatcher = new FileSystemWatcher
{
Path = path,
NotifyFilter = NotifyFilters.LastWrite,
};
_serverFilesWatcher.Changed += ServerFilesWatcher_Changed;
_serverFilesWatcher.Created += ServerFilesWatcher_Changed;
_serverFilesWatcher.Deleted += ServerFilesWatcher_Changed;
_serverFilesWatcher.Error += ServerFilesWatcher_Error;
_serverFilesWatcher.EnableRaisingEvents = true;
}
public void LoadServerFiles(bool blacklistFile, bool whitelistFile)
{
try
{
var list1 = this.ServerFilesBlacklisted ?? new PlayerUserList();
var list2 = this.ServerFilesWhitelisted ?? new PlayerUserList();
var allSteamIds = new List();
string[] blacklistSteamIds = null;
string[] whitelistSteamIds = null;
if (blacklistFile)
{
var file = Path.Combine(InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ServerBlacklistFile);
if (File.Exists(file))
{
blacklistSteamIds = File.ReadAllLines(file);
allSteamIds.AddRange(blacklistSteamIds);
}
}
if (whitelistFile)
{
var file = Path.Combine(InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ServerWhitelistFile);
if (File.Exists(file))
{
whitelistSteamIds = File.ReadAllLines(file);
allSteamIds.AddRange(whitelistSteamIds);
}
}
// remove all duplicates
allSteamIds = allSteamIds.Distinct().ToList();
// fetch the details of all steam users in the list
var steamUsers = SteamUtils.GetSteamUserDetails(allSteamIds);
if (blacklistFile && blacklistSteamIds != null)
{
list1 = PlayerUserList.GetList(steamUsers, blacklistSteamIds);
}
if (whitelistFile && whitelistSteamIds != null)
{
list2 = PlayerUserList.GetList(steamUsers, whitelistSteamIds);
}
this.ServerFilesBlacklisted = list1;
this.ServerFilesWhitelisted = list2;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_ServerFilesLoadErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
}
}
public void SaveServerFileBlacklisted()
{
try
{
var folder = Path.Combine(InstallDirectory, Config.Default.SavedFilesRelativePath);
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
var file = Path.Combine(folder, Config.Default.ServerBlacklistFile);
File.WriteAllLines(file, this.ServerFilesBlacklisted.ToEnumerable());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_ServerFilesSaveErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
}
}
public void SaveServerFileWhitelisted()
{
try
{
var folder = Path.Combine(InstallDirectory, Config.Default.SavedFilesRelativePath);
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
var file = Path.Combine(folder, Config.Default.ServerWhitelistFile);
File.WriteAllLines(file, this.ServerFilesWhitelisted.ToEnumerable());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_ServerFilesSaveErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
}
}
#endregion
#region Static Profile Methods
public static string GetProfileMapName(ServerProfile profile)
{
return GetProfileMapName(profile?.ServerMap);
}
public static string GetProfileMapName(string serverMap)
{
return ModUtils.GetMapName(serverMap);
}
public static string GetProfileSavePath(ServerProfile profile)
{
return GetProfileSavePath(profile?.InstallDirectory);
}
public static string GetProfileSavePath(string installDirectory)
{
return Path.Combine(installDirectory ?? string.Empty, Config.Default.SavedFilesRelativePath);
}
#endregion
#endregion
}
}