Server File Changes

- added Testlive server option
- changed code to use different appids.
This commit is contained in:
Brett Hewitson 2022-08-07 19:48:44 +10:00
parent 96ba2c3474
commit a20354c1b1
32 changed files with 969 additions and 812 deletions

View file

@ -71,9 +71,6 @@
<setting name="ProfileExtension" serializeAs="String">
<value>.profile</value>
</setting>
<setting name="DefaultDataDir" serializeAs="String">
<value>Ark Server Manager</value>
</setting>
<setting name="ServerProcessName" serializeAs="String">
<value>ShooterGameServer</value>
</setting>
@ -110,12 +107,6 @@
<setting name="AppPatchNotesUrlSotF" serializeAs="String">
<value>https://survivetheark.com/index.php?/forums/forum/9-changelog-patch-notes/</value>
</setting>
<setting name="AppUrl" serializeAs="String">
<value>https://store.steampowered.com/app/346110/</value>
</setting>
<setting name="AppUrl_SotF" serializeAs="String">
<value>https://store.steampowered.com/app/407530/</value>
</setting>
<setting name="LastUpdatedTimeFile" serializeAs="String">
<value>LastUpdatedASM.txt</value>
</setting>
@ -126,7 +117,7 @@
<value>+login {0} +workshop_download_item {1} {2} +quit</value>
</setting>
<setting name="AppSteamWorkshopFolderRelativePath" serializeAs="String">
<value>steamapps\workshop\content\346110\</value>
<value>steamapps\workshop\content\{0}\</value>
</setting>
<setting name="ServerModsRelativePath" serializeAs="String">
<value>ShooterGame\Content\Mods</value>
@ -138,7 +129,7 @@
<value>ShooterGame\Saved</value>
</setting>
<setting name="WorkshopCacheFile" serializeAs="String">
<value>workshopcache_346110.json</value>
<value>workshopcache_{0}.json</value>
</setting>
<setting name="SteamCmd_AnonymousUsername" serializeAs="String">
<value>anonymous</value>
@ -150,16 +141,7 @@
<value>steamapps\workshop</value>
</setting>
<setting name="AppSteamWorkshopFile" serializeAs="String">
<value>appworkshop_346110.acf</value>
</setting>
<setting name="AppSteamWorkshopFile_SotF" serializeAs="String">
<value>appworkshop_407530.acf</value>
</setting>
<setting name="AppSteamWorkshopFolderRelativePath_SotF" serializeAs="String">
<value>steamapps\workshop\content\407530\</value>
</setting>
<setting name="WorkshopCacheFile_SotF" serializeAs="String">
<value>workshopcache_407530.json</value>
<value>appworkshop_{0}.acf</value>
</setting>
<setting name="AppId" serializeAs="String">
<value>346110</value>
@ -303,10 +285,7 @@
<value>__</value>
</setting>
<setting name="AppSteamManifestFile" serializeAs="String">
<value>appmanifest_376030.acf</value>
</setting>
<setting name="AppSteamManifestFile_SotF" serializeAs="String">
<value>appmanifest_407530.acf</value>
<value>appmanifest_{0}.acf</value>
</setting>
<setting name="SteamManifestFolderRelativePath" serializeAs="String">
<value>steamapps</value>

View file

@ -191,15 +191,6 @@ namespace ServerManagerTool {
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("Ark Server Manager")]
public string DefaultDataDir {
get {
return ((string)(this["DefaultDataDir"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("ShooterGameServer")]
@ -585,24 +576,6 @@ namespace ServerManagerTool {
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("https://store.steampowered.com/app/346110/")]
public string AppUrl {
get {
return ((string)(this["AppUrl"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("https://store.steampowered.com/app/407530/")]
public string AppUrl_SotF {
get {
return ((string)(this["AppUrl_SotF"]));
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
@ -742,7 +715,7 @@ namespace ServerManagerTool {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("steamapps\\workshop\\content\\346110\\")]
[global::System.Configuration.DefaultSettingValueAttribute("steamapps\\workshop\\content\\{0}\\")]
public string AppSteamWorkshopFolderRelativePath {
get {
return ((string)(this["AppSteamWorkshopFolderRelativePath"]));
@ -862,7 +835,7 @@ namespace ServerManagerTool {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("workshopcache_346110.json")]
[global::System.Configuration.DefaultSettingValueAttribute("workshopcache_{0}.json")]
public string WorkshopCacheFile {
get {
return ((string)(this["WorkshopCacheFile"]));
@ -1042,7 +1015,7 @@ namespace ServerManagerTool {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("appworkshop_346110.acf")]
[global::System.Configuration.DefaultSettingValueAttribute("appworkshop_{0}.acf")]
public string AppSteamWorkshopFile {
get {
return ((string)(this["AppSteamWorkshopFile"]));
@ -1109,33 +1082,6 @@ namespace ServerManagerTool {
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("appworkshop_407530.acf")]
public string AppSteamWorkshopFile_SotF {
get {
return ((string)(this["AppSteamWorkshopFile_SotF"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("steamapps\\workshop\\content\\407530\\")]
public string AppSteamWorkshopFolderRelativePath_SotF {
get {
return ((string)(this["AppSteamWorkshopFolderRelativePath_SotF"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("workshopcache_407530.json")]
public string WorkshopCacheFile_SotF {
get {
return ((string)(this["WorkshopCacheFile_SotF"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("346110")]
@ -2086,22 +2032,13 @@ namespace ServerManagerTool {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("appmanifest_376030.acf")]
[global::System.Configuration.DefaultSettingValueAttribute("appmanifest_{0}.acf")]
public string AppSteamManifestFile {
get {
return ((string)(this["AppSteamManifestFile"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("appmanifest_407530.acf")]
public string AppSteamManifestFile_SotF {
get {
return ((string)(this["AppSteamManifestFile_SotF"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("steamapps")]

View file

@ -56,9 +56,6 @@
<Setting Name="DataDir" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="DefaultDataDir" Type="System.String" Scope="Application">
<Value Profile="(Default)">Ark Server Manager</Value>
</Setting>
<Setting Name="ServerProcessName" Type="System.String" Scope="Application">
<Value Profile="(Default)">ShooterGameServer</Value>
</Setting>
@ -164,12 +161,6 @@
<Setting Name="AppPatchNotesUrlSotF" Type="System.String" Scope="Application">
<Value Profile="(Default)">https://survivetheark.com/index.php?/forums/forum/9-changelog-patch-notes/</Value>
</Setting>
<Setting Name="AppUrl" Type="System.String" Scope="Application">
<Value Profile="(Default)">https://store.steampowered.com/app/346110/</Value>
</Setting>
<Setting Name="AppUrl_SotF" Type="System.String" Scope="Application">
<Value Profile="(Default)">https://store.steampowered.com/app/407530/</Value>
</Setting>
<Setting Name="RunAsAdministratorPrompt" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
@ -207,7 +198,7 @@
<Value Profile="(Default)">+login {0} +workshop_download_item {1} {2} +quit</Value>
</Setting>
<Setting Name="AppSteamWorkshopFolderRelativePath" Type="System.String" Scope="Application">
<Value Profile="(Default)">steamapps\workshop\content\346110\</Value>
<Value Profile="(Default)">steamapps\workshop\content\{0}\</Value>
</Setting>
<Setting Name="ServerModsRelativePath" Type="System.String" Scope="Application">
<Value Profile="(Default)">ShooterGame\Content\Mods</Value>
@ -240,7 +231,7 @@
<Value Profile="(Default)" />
</Setting>
<Setting Name="WorkshopCacheFile" Type="System.String" Scope="Application">
<Value Profile="(Default)">workshopcache_346110.json</Value>
<Value Profile="(Default)">workshopcache_{0}.json</Value>
</Setting>
<Setting Name="Email_Host" Type="System.String" Scope="User">
<Value Profile="(Default)" />
@ -288,7 +279,7 @@
<Value Profile="(Default)">steamapps\workshop</Value>
</Setting>
<Setting Name="AppSteamWorkshopFile" Type="System.String" Scope="Application">
<Value Profile="(Default)">appworkshop_346110.acf</Value>
<Value Profile="(Default)">appworkshop_{0}.acf</Value>
</Setting>
<Setting Name="SteamCmd_Password" Type="System.String" Scope="User">
<Value Profile="(Default)" />
@ -305,15 +296,6 @@
<Setting Name="ServerUpdate_OnServerStart" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="AppSteamWorkshopFile_SotF" Type="System.String" Scope="Application">
<Value Profile="(Default)">appworkshop_407530.acf</Value>
</Setting>
<Setting Name="AppSteamWorkshopFolderRelativePath_SotF" Type="System.String" Scope="Application">
<Value Profile="(Default)">steamapps\workshop\content\407530\</Value>
</Setting>
<Setting Name="WorkshopCacheFile_SotF" Type="System.String" Scope="Application">
<Value Profile="(Default)">workshopcache_407530.json</Value>
</Setting>
<Setting Name="AppId" Type="System.String" Scope="Application">
<Value Profile="(Default)">346110</Value>
</Setting>
@ -585,10 +567,7 @@
<Value Profile="(Default)">__</Value>
</Setting>
<Setting Name="AppSteamManifestFile" Type="System.String" Scope="Application">
<Value Profile="(Default)">appmanifest_376030.acf</Value>
</Setting>
<Setting Name="AppSteamManifestFile_SotF" Type="System.String" Scope="Application">
<Value Profile="(Default)">appmanifest_407530.acf</Value>
<Value Profile="(Default)">appmanifest_{0}.acf</Value>
</Setting>
<Setting Name="SteamManifestFolderRelativePath" Type="System.String" Scope="Application">
<Value Profile="(Default)">steamapps</Value>

View file

@ -9,6 +9,7 @@ namespace ServerManagerTool.Lib
{
}
public string AppIdServer = string.Empty;
public string BranchName = string.Empty;
public string BranchPassword = string.Empty;
@ -16,6 +17,7 @@ namespace ServerManagerTool.Lib
{
return new BranchSnapshot
{
AppIdServer = profile.SOTF_Enabled ? Config.Default.AppIdServer_SotF : string.Empty,
BranchName = profile.BranchName,
BranchPassword = profile.BranchPassword
};
@ -25,6 +27,7 @@ namespace ServerManagerTool.Lib
{
return new BranchSnapshot
{
AppIdServer = profile.AppIdServer,
BranchName = profile.BranchName,
BranchPassword = profile.BranchPassword
};
@ -42,17 +45,20 @@ namespace ServerManagerTool.Lib
if (x is null || y is null)
return false;
//Check whether the snapshot' properties are equal.
return string.Equals(x.BranchName ?? string.Empty, y.BranchName ?? string.Empty, StringComparison.OrdinalIgnoreCase);
//Check whether the snapshot properties are equal.
var result = string.Equals(x.AppIdServer ?? string.Empty, y.AppIdServer ?? string.Empty, StringComparison.OrdinalIgnoreCase);
return result && string.Equals(x.BranchName ?? string.Empty, y.BranchName ?? string.Empty, StringComparison.OrdinalIgnoreCase);
}
public int GetHashCode(BranchSnapshot snapshot)
{
//Check whether the object is null
if (snapshot is null) return 0;
if (snapshot is null)
return 0;
//Get hash code for the Name field if it is not null.
return snapshot.BranchName == null ? 0 : snapshot.BranchName.GetHashCode();
var result = $"{snapshot.AppIdServer ?? ""}-{snapshot.BranchName ?? ""}";
return result.GetHashCode();
}
}
}

View file

@ -830,7 +830,7 @@ namespace ServerManagerTool.Lib
}
}
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, _profile.InstallDirectory, _profile.SotFEnabled ? Config.Default.AppIdServer_SotF : Config.Default.AppIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, _profile.InstallDirectory, _profile.AppIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
if (steamCmdRemoveQuit)
{
SteamCMDProcessWindowStyle = ProcessWindowStyle.Normal;
@ -933,8 +933,8 @@ namespace ServerManagerTool.Lib
LogProfileMessage($"{modDetail.title}.\r\n");
}
var modCachePath = ModUtils.GetModCachePath(modId, _profile.SotFEnabled);
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, _profile.SotFEnabled);
var modCachePath = ModUtils.GetModCachePath(modId, _profile.AppId);
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, _profile.AppId);
var modPath = ModUtils.GetModPath(_profile.InstallDirectory, modId);
var modTimeFile = ModUtils.GetLatestModTimeFile(_profile.InstallDirectory, modId);
@ -1014,13 +1014,9 @@ namespace ServerManagerTool.Lib
steamCmdArgs = string.Empty;
if (Config.Default.SteamCmd_UseAnonymousCredentials)
{
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_AnonymousUsername, _profile.SotFEnabled ? Config.Default.AppId_SotF : Config.Default.AppId, modId);
}
else
{
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_Username, _profile.SotFEnabled ? Config.Default.AppId_SotF : Config.Default.AppId, modId);
}
modSuccess = ServerUpdater.UpgradeModsAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, Config.Default.SteamCmdRedirectOutput ? modOutputHandler : null, cancellationToken, SteamCMDProcessWindowStyle).Result;
if (modSuccess && downloadSuccessful)
@ -1039,7 +1035,7 @@ namespace ServerManagerTool.Lib
if (modDetail == null || modDetail.time_updated <= 0)
{
// get the version number from the steamcmd workshop file.
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(_profile.SotFEnabled), modId).ToString();
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(_profile.AppId), modId).ToString();
}
// update the last updated file with the steam updated time.
@ -1209,26 +1205,32 @@ namespace ServerManagerTool.Lib
LogProfileMessage("Started server update...");
LogProfileMessage("------------------------");
LogProfileMessage($"Server Manager version: {App.Instance.Version}");
LogProfileMessage($"Server branch: {GetBranchName(_profile.BranchName)}");
LogProfileMessage($"Server branch: {GetBranchInfo(_profile.AppIdServer, _profile.BranchName)}");
LogProfileMessage($"Profile Name: {_profile.ProfileName}");
// check if the server needs to be updated
var serverCacheLastUpdated = GetServerLatestTime(GetServerCacheTimeFile(_profile?.BranchName));
var serverCacheLastUpdated = GetServerLatestTime(GetServerCacheTimeFile(_profile.AppIdServer, _profile.BranchName));
var serverLastUpdated = GetServerLatestTime(GetServerTimeFile());
var updateServer = serverCacheLastUpdated > serverLastUpdated;
// check if any of the mods need to be updated
var updateModIds = new List<string>();
var modIdList = GetModList();
var appModList = GetModList();
// cycle through each mod.
foreach (var modId in modIdList)
foreach (var appMods in appModList)
{
// check if the mod needs to be updated.
var modCacheLastUpdated = ModUtils.GetModLatestTime(ModUtils.GetLatestModCacheTimeFile(modId, false));
var modLastUpdated = ModUtils.GetModLatestTime(ModUtils.GetLatestModTimeFile(_profile.InstallDirectory, modId));
if (modCacheLastUpdated > modLastUpdated || modLastUpdated == 0)
updateModIds.Add(modId);
if (!appMods.AppId.Equals(_profile.AppId, StringComparison.OrdinalIgnoreCase))
continue;
foreach (var modId in appMods.ModIdList)
{
// check if the mod needs to be updated.
var modCacheLastUpdated = ModUtils.GetModLatestTime(ModUtils.GetLatestModCacheTimeFile(modId, _profile.AppId));
var modLastUpdated = ModUtils.GetModLatestTime(ModUtils.GetLatestModTimeFile(_profile.InstallDirectory, modId));
if (modCacheLastUpdated > modLastUpdated || modLastUpdated == 0)
updateModIds.Add(modId);
}
}
if (ExitCode != EXITCODE_NORMALEXIT)
@ -1325,7 +1327,7 @@ namespace ServerManagerTool.Lib
try
{
var cacheFolder = GetServerCacheFolder(_profile?.BranchName);
var cacheFolder = GetServerCacheFolder(_profile.AppIdServer, _profile.BranchName);
if (Directory.Exists(cacheFolder))
{
@ -1347,13 +1349,14 @@ namespace ServerManagerTool.Lib
LogProfileMessage("Updated server from cache. See patch notes.");
LogProfileMessage(Config.Default.AppPatchNotesUrl);
LogProfileMessage(_profile.SotFEnabled ? Config.Default.AppPatchNotesUrlSotF : Config.Default.AppPatchNotesUrl);
if (!string.IsNullOrWhiteSpace(Config.Default.Alert_ServerUpdate))
alertMessage.AppendLine(Config.Default.Alert_ServerUpdate);
emailMessage.AppendLine();
emailMessage.AppendLine("Updated server from cache. See patch notes.");
emailMessage.AppendLine(Config.Default.AppPatchNotesUrl);
emailMessage.AppendLine(_profile.SotFEnabled ? Config.Default.AppPatchNotesUrlSotF : Config.Default.AppPatchNotesUrl);
_profile.ServerUpdated = true;
}
@ -1399,7 +1402,7 @@ namespace ServerManagerTool.Lib
for (var index = 0; index < updateModIds.Count; index++)
{
var modId = updateModIds[index];
var modCachePath = ModUtils.GetModCachePath(modId, false);
var modCachePath = ModUtils.GetModCachePath(modId, _profile.AppId);
var modPath = ModUtils.GetModPath(_profile.InstallDirectory, modId);
var modName = modDetails?.publishedfiledetails?.FirstOrDefault(m => m.publishedfileid == modId)?.title ?? string.Empty;
@ -1480,7 +1483,7 @@ namespace ServerManagerTool.Lib
}
else
{
if (modIdList.Count > 0)
if (appModList.Sum(m => m.ModIdList.Count) > 0)
LogProfileMessage("Mods are already up to date, no updates required.");
}
@ -1513,7 +1516,7 @@ namespace ServerManagerTool.Lib
else
{
LogProfileMessage("");
if (modIdList.Count > 0)
if (appModList.Sum(m => m.ModIdList.Count) > 0)
LogProfileMessage("The server and mods files are already up to date, no updates required.");
else
LogProfileMessage("The server files are already up to date, no updates required.");
@ -1549,10 +1552,10 @@ namespace ServerManagerTool.Lib
private void UpdateModCache()
{
// get a list of mods to be processed
var modIdList = GetModList();
var appModList = GetModList();
// check if there are any mods to be processed
if (modIdList.Count == 0)
if (appModList.Count == 0 || appModList.Sum(m => m.ModIdList.Count) == 0)
{
ExitCode = EXITCODE_NORMALEXIT;
return;
@ -1564,12 +1567,13 @@ namespace ServerManagerTool.Lib
LogMessage("----------------------------");
LogMessage($"Server Manager version: {App.Instance.Version}");
LogMessage($"Downloading mod information for {modIdList.Count} mods from steam.");
var totalMods = appModList.Sum(m => m.ModIdList.Count);
LogMessage($"Downloading mod information for {totalMods} mods from steam.");
var forceUpdateMods = Config.Default.ServerUpdate_ForceUpdateModsIfNoSteamInfo || string.IsNullOrWhiteSpace(SteamUtils.SteamWebApiKey);
// get the details of the mods to be processed.
var modDetails = SteamUtils.GetSteamModDetails(modIdList);
var modDetails = SteamUtils.GetSteamModDetails(appModList);
if (modDetails == null)
{
if (forceUpdateMods)
@ -1587,19 +1591,19 @@ namespace ServerManagerTool.Lib
}
else
{
LogMessage($"Downloaded mod information for {modIdList.Count} mods from steam.");
LogMessage($"Downloaded mod information for {totalMods} mods from steam.");
LogMessage("");
}
// cycle through each mod finding which needs to be updated.
var updateModIds = new List<string>();
var updateMods = new List<(string AppId, List<string> ModIdList)>();
if (modDetails == null)
{
if (forceUpdateMods)
{
LogMessage("All mods will be updated - unable to download steam information and force mod update is TRUE.");
updateModIds.AddRange(modIdList);
updateMods = appModList;
modDetails = new PublishedFileDetailsResponse();
}
}
@ -1608,46 +1612,67 @@ namespace ServerManagerTool.Lib
if (Config.Default.ServerUpdate_ForceUpdateMods)
{
LogMessage("All mods will be updated - force mod update is TRUE.");
updateModIds.AddRange(modIdList);
updateMods = appModList;
}
else
{
LogMessage("Mods will be selectively updated - force mod update is FALSE.");
foreach (var modId in modIdList)
foreach (var appMod in appModList)
{
var modDetail = modDetails.publishedfiledetails?.FirstOrDefault(m => m.publishedfileid.Equals(modId, StringComparison.OrdinalIgnoreCase));
if (modDetail == null)
foreach (var modId in appMod.ModIdList)
{
LogMessage($"Mod {modId} will not be updated - unable to download steam information.");
continue;
}
if (modDetail.time_updated == 0)
{
LogMessage($"Mod {modId} will be updated - mod is private.");
updateModIds.Add(modId);
}
else
{
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, false);
// check if the mod needs to be updated
var steamLastUpdated = modDetail.time_updated;
var modCacheLastUpdated = ModUtils.GetModLatestTime(cacheTimeFile);
if (steamLastUpdated > modCacheLastUpdated)
var modDetail = modDetails.publishedfiledetails?.FirstOrDefault(m => m.publishedfileid.Equals(modId, StringComparison.OrdinalIgnoreCase));
if (modDetail == null)
{
LogMessage($"Mod {modId} will be updated - new version found.");
updateModIds.Add(modId);
LogMessage($"Mod {modId} will not be updated - unable to download steam information.");
continue;
}
else if (modCacheLastUpdated == 0)
var updateMod = updateMods.FirstOrDefault(m => m.AppId.Equals(appMod.AppId, StringComparison.OrdinalIgnoreCase));
if (modDetail.time_updated == 0)
{
LogMessage($"Mod {modId} will be updated - cache not versioned.");
updateModIds.Add(modId);
LogMessage($"Mod {modId} will be updated - mod is private.");
if (updateMod == default)
updateMods.Add((appMod.AppId, new List<string> { modId }));
else
updateMod.ModIdList.Add(modId);
}
else
{
LogMessage($"Mod {modId} update skipped - cache contains the latest version.");
if (modDetail.creator_app_id is null || modDetail.creator_app_id.Equals(appMod.AppId, StringComparison.OrdinalIgnoreCase))
{
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, appMod.AppId);
// check if the mod needs to be updated
var steamLastUpdated = modDetail.time_updated;
var modCacheLastUpdated = ModUtils.GetModLatestTime(cacheTimeFile);
if (steamLastUpdated > modCacheLastUpdated)
{
LogMessage($"Mod {modId} will be updated - new version found.");
if (updateMod == default)
updateMods.Add((appMod.AppId, new List<string> { modId }));
else
updateMod.ModIdList.Add(modId);
}
else if (modCacheLastUpdated == 0)
{
LogMessage($"Mod {modId} will be updated - cache not versioned.");
if (updateMod == default)
updateMods.Add((appMod.AppId, new List<string> { modId }));
else
updateMod.ModIdList.Add(modId);
}
else
{
LogMessage($"Mod {modId} update skipped - cache contains the latest version.");
}
}
else
{
LogMessage($"Mod {modId} update skipped - mod does not belong to this application.");
}
}
}
}
@ -1662,97 +1687,105 @@ namespace ServerManagerTool.Lib
return;
}
var totalUpdateMods = updateMods.Sum(m => m.ModIdList.Count);
var updateIndex = 0;
// cycle through each mod id.
for (var index = 0; index < updateModIds.Count; index++)
foreach (var appMod in updateMods)
{
var modId = updateModIds[index];
var modDetail = modDetails.publishedfiledetails?.FirstOrDefault(m => m.publishedfileid.Equals(modId, StringComparison.OrdinalIgnoreCase));
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, false);
var modCachePath = ModUtils.GetModCachePath(modId, false);
var downloadSuccessful = false;
DataReceivedEventHandler modOutputHandler = (s, e) =>
for (var index = 0; index < appMod.ModIdList.Count; index++)
{
var dataValue = e.Data ?? string.Empty;
LogMessage(dataValue);
if (dataValue.StartsWith("Success."))
var modId = appMod.ModIdList[index];
var modDetail = modDetails.publishedfiledetails?.FirstOrDefault(m => m.publishedfileid.Equals(modId, StringComparison.OrdinalIgnoreCase));
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, appMod.AppId);
var modCachePath = ModUtils.GetModCachePath(modId, appMod.AppId);
var downloadSuccessful = false;
DataReceivedEventHandler modOutputHandler = (s, e) =>
{
downloadSuccessful = true;
}
};
LogMessage("");
LogMessage($"Started mod cache update {index + 1} of {updateModIds.Count}");
LogMessage($"{modId} - {modDetail?.title ?? "<unknown>"}");
var attempt = 0;
while (true)
{
attempt++;
downloadSuccessful = !Config.Default.SteamCmdRedirectOutput;
// update the mod cache
var steamCmdArgs = string.Empty;
if (Config.Default.SteamCmd_UseAnonymousCredentials)
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_AnonymousUsername, Config.Default.AppId, modId);
else
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_Username, Config.Default.AppId, modId);
var workingDirectory = Config.Default.DataDir;
var success = ServerUpdater.UpgradeModsAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, Config.Default.SteamCmdRedirectOutput ? modOutputHandler : null, CancellationToken.None, SteamCMDProcessWindowStyle).Result;
if (success && downloadSuccessful)
// download was successful, exit loop and continue.
break;
// download was not successful, log a failed attempt.
var logError = $"Mod {modId} cache update failed";
if (Config.Default.AutoUpdate_RetryOnFail)
logError += $" - attempt {attempt}.";
LogError(logError);
// check if we have reached the max failed attempt limit.
if (!Config.Default.AutoUpdate_RetryOnFail || attempt >= MAXRETRIES_STEAM)
{
// failed max limit reached
if (Config.Default.SteamCmdRedirectOutput)
var dataValue = e.Data ?? string.Empty;
LogMessage(dataValue);
if (dataValue.StartsWith("Success."))
{
LogMessage("Check steamcmd logs for more information why the mod cache update failed.\r\n");
LogMessage($"If the mod cache update keeps failing try disabling the '{_globalizer.GetResourceString("GlobalSettings_SteamCmdRedirectOutputLabel")}' option in the Server Manager settings window.");
downloadSuccessful = true;
}
};
updateIndex++;
LogMessage("");
LogMessage($"Started mod cache update {updateIndex} of {totalUpdateMods}");
LogMessage($"{modId} - {modDetail?.title ?? "<unknown>"}");
var attempt = 0;
while (true)
{
attempt++;
downloadSuccessful = !Config.Default.SteamCmdRedirectOutput;
// update the mod cache
var steamCmdArgs = string.Empty;
if (Config.Default.SteamCmd_UseAnonymousCredentials)
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_AnonymousUsername, appMod.AppId, modId);
else
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_Username, appMod.AppId, modId);
var workingDirectory = Config.Default.DataDir;
var success = ServerUpdater.UpgradeModsAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, Config.Default.SteamCmdRedirectOutput ? modOutputHandler : null, CancellationToken.None, SteamCMDProcessWindowStyle).Result;
if (success && downloadSuccessful)
// download was successful, exit loop and continue.
break;
// download was not successful, log a failed attempt.
var logError = $"Mod {modId} cache update failed";
if (Config.Default.AutoUpdate_RetryOnFail)
logError += $" - attempt {attempt}.";
LogError(logError);
// check if we have reached the max failed attempt limit.
if (!Config.Default.AutoUpdate_RetryOnFail || attempt >= MAXRETRIES_STEAM)
{
// failed max limit reached
if (Config.Default.SteamCmdRedirectOutput)
{
LogMessage("Check steamcmd logs for more information why the mod cache update failed.\r\n");
LogMessage($"If the mod cache update keeps failing try disabling the '{_globalizer.GetResourceString("GlobalSettings_SteamCmdRedirectOutputLabel")}' option in the Server Manager settings window.");
}
ExitCode = EXITCODE_CACHEMODUPDATEFAILED;
return;
}
ExitCode = EXITCODE_CACHEMODUPDATEFAILED;
return;
Task.Delay(5000).Wait();
}
Task.Delay(5000).Wait();
}
// check if any of the mod files have changed.
if (Directory.Exists(modCachePath))
{
var gotNewVersion = new DirectoryInfo(modCachePath).GetFiles("*.*", SearchOption.AllDirectories).Any(file => file.LastWriteTime >= _startTime);
if (gotNewVersion)
LogMessage("***** New version downloaded. *****");
else
LogMessage("No new version.");
var steamLastUpdated = modDetail?.time_updated.ToString() ?? string.Empty;
if (modDetail == null || modDetail.time_updated <= 0)
// check if any of the mod files have changed.
if (Directory.Exists(modCachePath))
{
// get the version number from the steamcmd workshop file.
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(false), modId).ToString();
var gotNewVersion = new DirectoryInfo(modCachePath).GetFiles("*.*", SearchOption.AllDirectories).Any(file => file.LastWriteTime >= _startTime);
if (gotNewVersion)
LogMessage("***** New version downloaded. *****");
else
LogMessage("No new version.");
var steamLastUpdated = modDetail?.time_updated.ToString() ?? string.Empty;
if (modDetail == null || modDetail.time_updated <= 0)
{
// get the version number from the steamcmd workshop file.
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(appMod.AppId), modId).ToString();
}
File.WriteAllText(cacheTimeFile, steamLastUpdated);
LogMessage($"Mod {modId} cache version: {steamLastUpdated}");
}
else
LogMessage($"Mod {modId} cache does not exist.");
File.WriteAllText(cacheTimeFile, steamLastUpdated);
LogMessage($"Mod {modId} cache version: {steamLastUpdated}");
LogMessage($"Finished mod {modId} cache update.");
}
else
LogMessage($"Mod {modId} cache does not exist.");
LogMessage($"Finished mod {modId} cache update.");
}
LogMessage("---------------------------");
@ -1762,13 +1795,13 @@ namespace ServerManagerTool.Lib
ExitCode = EXITCODE_NORMALEXIT;
}
private void UpdateServerCache(string branchName, string branchPassword)
private void UpdateServerCache(string appIdServer, string branchName, string branchPassword)
{
LogBranchMessage(branchName, "-------------------------------");
LogBranchMessage(branchName, "Starting server cache update...");
LogBranchMessage(branchName, "-------------------------------");
LogBranchMessage(branchName, $"Server Manager version: {App.Instance.Version}");
LogBranchMessage(branchName, $"Server branch: {GetBranchName(branchName)}");
LogBranchMessage(appIdServer, branchName, "-------------------------------");
LogBranchMessage(appIdServer, branchName, "Starting server cache update...");
LogBranchMessage(appIdServer, branchName, "-------------------------------");
LogBranchMessage(appIdServer, branchName, $"Server Manager version: {App.Instance.Version}");
LogBranchMessage(appIdServer, branchName, $"Server branch: {GetBranchInfo(appIdServer, branchName)}");
var gotNewVersion = false;
var downloadSuccessful = false;
@ -1776,7 +1809,7 @@ namespace ServerManagerTool.Lib
var steamCmdFile = SteamCmdUpdater.GetSteamCmdFile(Config.Default.DataDir);
if (string.IsNullOrWhiteSpace(steamCmdFile) || !File.Exists(steamCmdFile))
{
LogBranchError(branchName, $"SteamCMD could not be found. Expected location is {steamCmdFile}");
LogBranchError(appIdServer, branchName, $"SteamCMD could not be found. Expected location is {steamCmdFile}");
ExitCode = EXITCODE_STEAMCMDNOTFOUND;
return;
}
@ -1784,7 +1817,7 @@ namespace ServerManagerTool.Lib
DataReceivedEventHandler serverOutputHandler = (s, e) =>
{
var dataValue = e.Data ?? string.Empty;
LogBranchMessage(branchName, dataValue);
LogBranchMessage(appIdServer, branchName, dataValue);
if (!gotNewVersion && dataValue.Contains("downloading,"))
{
gotNewVersion = true;
@ -1807,9 +1840,9 @@ namespace ServerManagerTool.Lib
}
}
var cacheFolder = GetServerCacheFolder(branchName);
var cacheFolder = GetServerCacheFolder(appIdServer, branchName);
LogBranchMessage(branchName, "Server update started.");
LogBranchMessage(appIdServer, branchName, "Server update started.");
var attempt = 0;
while (true)
@ -1820,7 +1853,7 @@ namespace ServerManagerTool.Lib
// update the server cache
var validate = Config.Default.AutoUpdate_ValidateServerFiles;
var steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, cacheFolder, Config.Default.AppIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
var steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, cacheFolder, appIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
var workingDirectory = Config.Default.DataDir;
var success = ServerUpdater.UpgradeServerAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, cacheFolder, Config.Default.SteamCmdRedirectOutput ? serverOutputHandler : null, CancellationToken.None, SteamCMDProcessWindowStyle).Result;
@ -1832,7 +1865,7 @@ namespace ServerManagerTool.Lib
var logError = "Server cache update failed";
if (Config.Default.AutoUpdate_RetryOnFail)
logError += $" - attempt {attempt}.";
LogBranchError(branchName, logError);
LogBranchError(appIdServer, branchName, logError);
// check if we have reached the max failed attempt limit.
if (!Config.Default.AutoUpdate_RetryOnFail || attempt >= MAXRETRIES_STEAM)
@ -1840,8 +1873,8 @@ namespace ServerManagerTool.Lib
// failed max limit reached
if (Config.Default.SteamCmdRedirectOutput)
{
LogBranchMessage(branchName, $"Check steamcmd logs for more information why the server cache update failed.\r\n");
LogBranchMessage(branchName, $"If the server cache update keeps failing try disabling the '{_globalizer.GetResourceString("GlobalSettings_SteamCmdRedirectOutputLabel")}' option in the ASM settings window.");
LogBranchMessage(appIdServer, branchName, $"Check steamcmd logs for more information why the server cache update failed.\r\n");
LogBranchMessage(appIdServer, branchName, $"If the server cache update keeps failing try disabling the '{_globalizer.GetResourceString("GlobalSettings_SteamCmdRedirectOutputLabel")}' option in the server manager settings window.");
}
ExitCode = EXITCODE_CACHESERVERUPDATEFAILED;
@ -1859,24 +1892,24 @@ namespace ServerManagerTool.Lib
if (gotNewVersion)
{
LogBranchMessage(branchName, "***** New version downloaded. *****");
LogBranchMessage(appIdServer, branchName, "***** New version downloaded. *****");
var latestCacheTimeFile = GetServerCacheTimeFile(branchName);
var latestCacheTimeFile = GetServerCacheTimeFile(appIdServer, branchName);
File.WriteAllText(latestCacheTimeFile, _startTime.ToString("o", CultureInfo.CurrentCulture));
}
else
LogBranchMessage(branchName, "No new version.");
LogBranchMessage(appIdServer, branchName, "No new version.");
}
else
LogBranchMessage(branchName, $"Server cache does not exist.");
LogBranchMessage(appIdServer, branchName, $"Server cache does not exist.");
var cacheVersion = GetServerVersion(GetServerCacheVersionFile(branchName)).ToString();
LogBranchMessage(branchName, $"Server cache version: {cacheVersion}");
var cacheVersion = GetServerVersion(GetServerCacheVersionFile(appIdServer, branchName)).ToString();
LogBranchMessage(appIdServer, branchName, $"Server cache version: {cacheVersion}");
LogBranchMessage(branchName, "-----------------------------");
LogBranchMessage(branchName, "Finished server cache update.");
LogBranchMessage(branchName, "-----------------------------");
LogBranchMessage(branchName, "");
LogBranchMessage(appIdServer, branchName, "-----------------------------");
LogBranchMessage(appIdServer, branchName, "Finished server cache update.");
LogBranchMessage(appIdServer, branchName, "-----------------------------");
LogBranchMessage(appIdServer, branchName, "");
ExitCode = EXITCODE_NORMALEXIT;
}
@ -2320,7 +2353,14 @@ namespace ServerManagerTool.Lib
}
}
public static string GetBranchName(string branchName) => string.IsNullOrWhiteSpace(branchName) ? Config.Default.DefaultServerBranchName : branchName;
public static string GetBranchInfo(string appIdServer, string branchName)
{
var branchInfo = string.IsNullOrWhiteSpace(branchName) ? Config.Default.DefaultServerBranchName : branchName;
if (!string.IsNullOrWhiteSpace(appIdServer) && !appIdServer.Equals(Config.Default.AppIdServer, StringComparison.OrdinalIgnoreCase))
branchInfo += $"_{appIdServer}";
return branchInfo;
}
private string GetLauncherFile() => IOUtils.NormalizePath(Path.Combine(GetProfileServerConfigDir(_profile), Config.Default.LauncherFile));
@ -2367,9 +2407,9 @@ namespace ServerManagerTool.Lib
return LogManager.GetLogger(loggerName);
}
private List<string> GetModList()
private List<(string AppId, List<string> ModIdList)> GetModList()
{
var modIdList = new List<string>();
var appMods = new List<(string AppId, List<string> ModIdList)>();
// check if we need to update the mods.
if (Config.Default.ServerUpdate_UpdateModsWhenUpdatingServer)
@ -2383,6 +2423,8 @@ namespace ServerManagerTool.Lib
if (!profile.EnableAutoUpdate)
continue;
var modIdList = new List<string>();
if (!string.IsNullOrWhiteSpace(profile.ServerMapModId))
modIdList.Add(profile.ServerMapModId);
@ -2390,11 +2432,19 @@ namespace ServerManagerTool.Lib
modIdList.Add(profile.TotalConversionModId);
modIdList.AddRange(profile.ServerModIds);
var appMod = appMods.FirstOrDefault(m => m.AppId.Equals(profile.AppId, StringComparison.OrdinalIgnoreCase));
if (appMod == default)
appMods.Add((profile.AppId, modIdList));
else
appMod.ModIdList.AddRange(modIdList);
}
}
else
{
// get all the mods for only the specified profile.
var modIdList = new List<string>();
if (!string.IsNullOrWhiteSpace(_profile.ServerMapModId))
modIdList.Add(_profile.ServerMapModId);
@ -2402,10 +2452,19 @@ namespace ServerManagerTool.Lib
modIdList.Add(_profile.TotalConversionModId);
modIdList.AddRange(_profile.ServerModIds);
appMods.Add((_profile.AppId, modIdList));
}
}
return ModUtils.ValidateModList(modIdList);
for (int i = 0; i < appMods.Count; i++)
{
var validatedModList = ModUtils.ValidateModList(appMods[i].ModIdList);
appMods[i].ModIdList.Clear();
appMods[i].ModIdList.AddRange(validatedModList);
}
return appMods;
}
public static string GetMutexName(string directory)
@ -2469,11 +2528,15 @@ namespace ServerManagerTool.Lib
return IOUtils.NormalizePath(Path.Combine(Config.Default.BackupPath, Config.Default.ServersInstallDir, profile.ProfileId.ToLower()));
}
private static string GetServerCacheFolder(string branchName) => IOUtils.NormalizePath(Path.Combine(Config.Default.AutoUpdate_CacheDir, $"{Config.Default.ServerBranchFolderPrefix}{GetBranchName(branchName)}"));
public static string GetServerCacheFolder(string appIdServer, string branchName)
{
var branchInfo = GetBranchInfo(appIdServer, branchName) ?? "unknown";
return IOUtils.NormalizePath(Path.Combine(Config.Default.AutoUpdate_CacheDir, $"{Config.Default.ServerBranchFolderPrefix}{branchInfo}"));
}
private static string GetServerCacheTimeFile(string branchName) => IOUtils.NormalizePath(Path.Combine(GetServerCacheFolder(branchName), Config.Default.LastUpdatedTimeFile));
private static string GetServerCacheTimeFile(string appIdServer, string branchName) => IOUtils.NormalizePath(Path.Combine(GetServerCacheFolder(appIdServer, branchName), Config.Default.LastUpdatedTimeFile));
private static string GetServerCacheVersionFile(string branchName) => IOUtils.NormalizePath(Path.Combine(GetServerCacheFolder(branchName), Config.Default.VersionFile));
private static string GetServerCacheVersionFile(string appIdServer, string branchName) => IOUtils.NormalizePath(Path.Combine(GetServerCacheFolder(appIdServer, branchName), Config.Default.VersionFile));
private string GetServerExecutableFile() => IOUtils.NormalizePath(Path.Combine(_profile.InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ServerExe));
@ -2640,7 +2703,7 @@ namespace ServerManagerTool.Lib
Debug.WriteLine($"[INFO] {message}");
}
private void LogBranchError(string branchName, string error, bool includeProgressCallback = true)
private void LogBranchError(string appIdServer, string branchName, string error, bool includeProgressCallback = true)
{
if (string.IsNullOrWhiteSpace(error))
return;
@ -2650,10 +2713,12 @@ namespace ServerManagerTool.Lib
if (includeProgressCallback)
ProgressCallback?.Invoke(0, $"[ERROR] {error}");
Debug.WriteLine($"[ERROR] (Branch {GetBranchName(branchName) ?? "unknown"}) {error}");
var branchInfo = GetBranchInfo(appIdServer, branchName) ?? "unknown";
Debug.WriteLine($"[ERROR] (Branch {branchInfo}) {error}");
}
private void LogBranchMessage(string branchName, string message, bool includeProgressCallback = true)
private void LogBranchMessage(string appIdServer, string branchName, string message, bool includeProgressCallback = true)
{
message = message ?? string.Empty;
@ -2662,7 +2727,9 @@ namespace ServerManagerTool.Lib
if (includeProgressCallback)
ProgressCallback?.Invoke(0, $"{message}");
Debug.WriteLine($"[INFO] (Branch {GetBranchName(branchName) ?? "unknown"}) {message}");
var branchInfo = GetBranchInfo(appIdServer, branchName) ?? "unknown";
Debug.WriteLine($"[INFO] (Branch {branchInfo}) {message}");
}
private void LogProfileDebug(string message, bool includeProgressCallback = true)
@ -3081,16 +3148,17 @@ namespace ServerManagerTool.Lib
Mutex mutex = null;
var createdNew = false;
var branchInfo = GetBranchInfo(branch.AppIdServer, branch.BranchName) ?? "unknown";
if (OutputLogs)
{
_loggerBranch = GetLogger(GetLogFolder(LOGPREFIX_AUTOUPDATE), $"{LOGPREFIX_AUTOUPDATE}", $"BranchUpdate_{GetBranchName(branch.BranchName)}");
_loggerBranch = GetLogger(GetLogFolder(LOGPREFIX_AUTOUPDATE), $"{LOGPREFIX_AUTOUPDATE}", $"BranchUpdate_{branchInfo}");
_loggerProfile = GetLogger(GetProfileLogFolder(profile.ProfileId, LOGPREFIX_AUTOUPDATE), $"{LOGPREFIX_AUTOUPDATE}_{profile.ProfileId}", "Update");
}
try
{
LogBranchMessage(branch.BranchName, $"[{_profile.ProfileName}] Started server update process.");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"[{_profile.ProfileName}] Started server update process.");
// try to establish a mutex for the profile.
var mutexName = GetMutexName(_profile.InstallDirectory);
@ -3111,7 +3179,7 @@ namespace ServerManagerTool.Lib
UpdateFiles();
LogBranchMessage(branch.BranchName, $"[{_profile.ProfileName}] Finished server update process.");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"[{_profile.ProfileName}] Finished server update process.");
if (ExitCode != EXITCODE_NORMALEXIT)
{
@ -3124,7 +3192,7 @@ namespace ServerManagerTool.Lib
{
ExitCode = EXITCODE_PROCESSALREADYRUNNING;
LogProfileMessage("Cancelled server update process, could not lock server.");
LogBranchMessage(branch.BranchName, $"[{_profile.ProfileName}] Cancelled server update process, could not lock server.");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"[{_profile.ProfileName}] Cancelled server update process, could not lock server.");
}
}
catch (Exception ex)
@ -3171,47 +3239,50 @@ namespace ServerManagerTool.Lib
Mutex mutex = null;
var createdNew = false;
var branchInfo = GetBranchInfo(branch.AppIdServer, branch.BranchName) ?? "unknown";
if (OutputLogs)
_loggerBranch = GetLogger(GetLogFolder(LOGPREFIX_AUTOUPDATE), $"{LOGPREFIX_AUTOUPDATE}", $"BranchUpdate_{GetBranchName(branch.BranchName)}");
{
_loggerBranch = GetLogger(GetLogFolder(LOGPREFIX_AUTOUPDATE), $"{LOGPREFIX_AUTOUPDATE}", $"BranchUpdate_{branchInfo}");
}
try
{
LogMessage($"[{GetBranchName(branch.BranchName)}] Started branch update process.");
LogMessage($"[{branchInfo}] Started branch update process.");
var cacheFolder = GetServerCacheFolder(branch.BranchName);
var cacheFolder = GetServerCacheFolder(branch.AppIdServer, branch.BranchName);
// try to establish a mutex for the profile.
var mutexName = GetMutexName(cacheFolder);
LogBranchMessage(branch.BranchName, $"Attempting to establish a lock on the cache ({mutexName})");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"Attempting to establish a lock on the cache ({mutexName})");
mutex = new Mutex(true, mutexName, out createdNew);
if (!createdNew)
{
var timeout = new TimeSpan(0, MUTEX_TIMEOUT, 0);
LogBranchMessage(branch.BranchName, $"Could not lock cache, waiting for cache to unlock - timeout set to {timeout}.");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"Could not lock cache, waiting for cache to unlock - timeout set to {timeout}.");
createdNew = mutex.WaitOne(timeout);
}
// check if the mutex was established
if (createdNew)
{
LogBranchMessage(branch.BranchName, "Cache lock established.\r\n");
LogBranchMessage(branch.AppIdServer, branch.BranchName, "Cache lock established.\r\n");
// update the server cache for the branch
UpdateServerCache(branch.BranchName, branch.BranchPassword);
UpdateServerCache(branch.AppIdServer, branch.BranchName, branch.BranchPassword);
if (ExitCode != EXITCODE_NORMALEXIT)
{
if (Config.Default.EmailNotify_AutoUpdate)
SendEmail($"{GetBranchName(branch.BranchName)} branch update", Config.Default.Alert_UpdateProcessError, true);
SendEmail($"{branchInfo} branch update", Config.Default.Alert_UpdateProcessError, true);
ProcessAlert(AlertType.Error, Config.Default.Alert_UpdateProcessError);
}
if (ExitCode == EXITCODE_NORMALEXIT)
{
// get the profile associated with the branch
var profiles = _profiles.Keys.Where(p => p.EnableAutoUpdate && string.Equals(p.BranchName, branch.BranchName, StringComparison.OrdinalIgnoreCase));
var profiles = _profiles.Keys.Where(p => p.EnableAutoUpdate && string.Equals(p.AppIdServer, branch.AppIdServer, StringComparison.OrdinalIgnoreCase) && string.Equals(p.BranchName, branch.BranchName, StringComparison.OrdinalIgnoreCase));
var profileExitCodes = new ConcurrentDictionary<ServerProfileSnapshot, int>();
if (Config.Default.AutoUpdate_ParallelUpdate)
@ -3256,27 +3327,27 @@ namespace ServerManagerTool.Lib
ExitCode = EXITCODE_EXITWITHERRORS;
}
LogMessage($"[{GetBranchName(branch.BranchName)}] Finished branch update process.");
LogMessage($"[{branchInfo}] Finished branch update process.");
}
else
{
ExitCode = EXITCODE_PROCESSALREADYRUNNING;
LogMessage($"[{GetBranchName(branch.BranchName)}] Cancelled branch update process, could not lock cache.");
LogMessage($"[{branchInfo}] Cancelled branch update process, could not lock cache.");
}
}
catch (Exception ex)
{
LogBranchError(branch.BranchName, ex.Message);
LogBranchError(branch.BranchName, ex.GetType().ToString());
LogBranchError(branch.AppIdServer, branch.BranchName, ex.Message);
LogBranchError(branch.AppIdServer, branch.BranchName, ex.GetType().ToString());
if (ex.InnerException != null)
{
LogBranchMessage(branch.BranchName, $"InnerException - {ex.InnerException.Message}");
LogBranchMessage(branch.BranchName, ex.InnerException.GetType().ToString());
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"InnerException - {ex.InnerException.Message}");
LogBranchMessage(branch.AppIdServer, branch.BranchName, ex.InnerException.GetType().ToString());
}
LogBranchMessage(branch.BranchName, $"StackTrace\r\n{ex.StackTrace}");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"StackTrace\r\n{ex.StackTrace}");
if (Config.Default.EmailNotify_AutoUpdate)
SendEmail($"{GetBranchName(branch.BranchName)} branch update", Config.Default.Alert_UpdateProcessError, true);
SendEmail($"{branchInfo} branch update", Config.Default.Alert_UpdateProcessError, true);
ProcessAlert(AlertType.Error, Config.Default.Alert_UpdateProcessError);
ExitCode = EXITCODE_UNKNOWNTHREADERROR;
}
@ -3293,8 +3364,8 @@ namespace ServerManagerTool.Lib
}
}
LogBranchMessage(branch.BranchName, "");
LogBranchMessage(branch.BranchName, $"Exitcode = {ExitCode}");
LogBranchMessage(branch.AppIdServer, branch.BranchName, "");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"Exitcode = {ExitCode}");
return ExitCode;
}

View file

@ -3642,7 +3642,8 @@ namespace ServerManagerTool.Lib
try
{
var manifestFile = ModUtils.GetSteamManifestFile(InstallDirectory, SOTF_Enabled);
var appIdServer = SOTF_Enabled ? Config.Default.AppIdServer_SotF : Config.Default.AppIdServer;
var manifestFile = ModUtils.GetSteamManifestFile(InstallDirectory, appIdServer);
if (string.IsNullOrWhiteSpace(manifestFile) || !File.Exists(manifestFile))
return;

View file

@ -29,13 +29,15 @@ namespace ServerManagerTool.Lib
public string ServerMap;
public string ServerMapModId;
public string TotalConversionModId;
public IEnumerable<string> ServerModIds;
public List<string> ServerModIds;
public string MOTD;
public int MOTDDuration;
public bool MOTDIntervalEnabled;
public int MOTDInterval;
public bool ForceRespawnDinos;
public string AppId;
public string AppIdServer;
public string BranchName;
public string BranchPassword;
@ -87,6 +89,8 @@ namespace ServerManagerTool.Lib
MOTDInterval = Math.Max(1, Math.Min(int.MaxValue, profile.MOTDInterval.Value)),
ForceRespawnDinos = profile.ForceRespawnDinos,
AppId = profile.SOTF_Enabled ? Config.Default.AppId_SotF : Config.Default.AppId,
AppIdServer = profile.SOTF_Enabled ? Config.Default.AppIdServer_SotF : Config.Default.AppIdServer,
BranchName = profile.BranchName,
BranchPassword = profile.BranchPassword,

View file

@ -660,8 +660,10 @@ namespace ServerManagerTool.Lib
// Server Update Section
// *********************
var branchInfo = ServerApp.GetBranchInfo(branch?.AppIdServer, branch?.BranchName);
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} Starting server update.");
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} Server branch: {ServerApp.GetBranchName(branch?.BranchName)}.");
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} Server branch: {branchInfo}.");
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} Profile name: {this.ProfileSnapshot.ProfileName}.");
// create the branch arguments
@ -677,10 +679,9 @@ namespace ServerManagerTool.Lib
}
// Check if this is a new server installation.
if (isNewInstallation && !this.ProfileSnapshot.SotFEnabled && Config.Default.AutoUpdate_EnableUpdate && !string.IsNullOrWhiteSpace(Config.Default.AutoUpdate_CacheDir))
if (isNewInstallation && Config.Default.AutoUpdate_EnableUpdate && !string.IsNullOrWhiteSpace(Config.Default.AutoUpdate_CacheDir))
{
var branchName = string.IsNullOrWhiteSpace(branch?.BranchName) ? Config.Default.DefaultServerBranchName : branch.BranchName;
var cacheFolder = IOUtils.NormalizePath(Path.Combine(Config.Default.AutoUpdate_CacheDir, $"{Config.Default.ServerBranchFolderPrefix}{branchName}"));
var cacheFolder = ServerApp.GetServerCacheFolder(branch?.AppIdServer, branch?.BranchName);
// check if the auto-update facility is enabled and the cache folder defined.
if (!string.IsNullOrWhiteSpace(cacheFolder) && Directory.Exists(cacheFolder))
@ -719,7 +720,7 @@ namespace ServerManagerTool.Lib
};
var steamCmdRemoveQuit = CommonConfig.Default.SteamCmdRemoveQuit && !Config.Default.SteamCmdRedirectOutput;
var steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, this.ProfileSnapshot.InstallDirectory, Config.Default.AppIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
var steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, this.ProfileSnapshot.InstallDirectory, this.ProfileSnapshot.AppIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
var workingDirectory = Config.Default.DataDir;
success = await ServerUpdater.UpgradeServerAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, this.ProfileSnapshot.InstallDirectory, Config.Default.SteamCmdRedirectOutput ? serverOutputHandler : null, cancellationToken, steamCmdRemoveQuit ? ProcessWindowStyle.Normal : ProcessWindowStyle.Minimized);
@ -813,16 +814,27 @@ namespace ServerManagerTool.Lib
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} Mod {modTitle}.");
var modCachePath = ModUtils.GetModCachePath(modId, this.ProfileSnapshot.SotFEnabled);
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, this.ProfileSnapshot.SotFEnabled);
var modPath = ModUtils.GetModPath(this.ProfileSnapshot.InstallDirectory, modId);
var modTimeFile = ModUtils.GetLatestModTimeFile(this.ProfileSnapshot.InstallDirectory, modId);
var modCacheLastUpdated = 0;
var downloadMod = true;
var copyMod = true;
var updateError = false;
if (modDetail?.creator_app_id != null && !modDetail.creator_app_id.Equals(this.ProfileSnapshot.AppId, StringComparison.OrdinalIgnoreCase))
{
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} ***************************************************************************");
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} ERROR: Mod cannot be updated, this mod does not belong to this application.");
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} ***************************************************************************");
downloadMod = false;
copyMod = false;
updateError = true;
}
var modCachePath = ModUtils.GetModCachePath(modId, this.ProfileSnapshot.AppId);
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, this.ProfileSnapshot.AppId);
var modPath = ModUtils.GetModPath(this.ProfileSnapshot.InstallDirectory, modId);
var modTimeFile = ModUtils.GetLatestModTimeFile(this.ProfileSnapshot.InstallDirectory, modId);
if (downloadMod)
{
// check if the mod needs to be downloaded, or force the download.
@ -895,9 +907,9 @@ namespace ServerManagerTool.Lib
var steamCmdArgs = string.Empty;
var steamCmdRemoveQuit = CommonConfig.Default.SteamCmdRemoveQuit && !Config.Default.SteamCmdRedirectOutput;
if (Config.Default.SteamCmd_UseAnonymousCredentials)
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_AnonymousUsername, this.ProfileSnapshot.SotFEnabled ? Config.Default.AppId_SotF : Config.Default.AppId, modId);
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_AnonymousUsername, this.ProfileSnapshot.AppId, modId);
else
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_Username, this.ProfileSnapshot.SotFEnabled ? Config.Default.AppId_SotF : Config.Default.AppId, modId);
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_Username, this.ProfileSnapshot.AppId, modId);
var workingDirectory = Config.Default.DataDir;
modSuccess = await ServerUpdater.UpgradeModsAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, Config.Default.SteamCmdRedirectOutput ? modOutputHandler : null, cancellationToken, steamCmdRemoveQuit ? ProcessWindowStyle.Normal : ProcessWindowStyle.Minimized);
@ -917,7 +929,7 @@ namespace ServerManagerTool.Lib
if (modDetail == null || modDetail.time_updated <= 0)
{
// get the version number from the steamcmd workshop file.
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(this.ProfileSnapshot.SotFEnabled), modId).ToString();
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(this.ProfileSnapshot.AppId), modId).ToString();
}
// update the last updated file with the steam updated time.

View file

@ -6497,9 +6497,6 @@
<GroupBox.Header>
<StackPanel Orientation="Horizontal">
<cctl:CheckBoxAndTextBlock Name="EnableSOTFCheckbox" IsChecked="{Binding SOTF_Enabled, Mode=TwoWay, NotifyOnSourceUpdated=True}" IsEnabled="{Binding ElementName=EnablePGMCheckbox, Path=IsChecked, Converter={StaticResource InvertBooleanConverter}, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" Text="{DynamicResource ServerSettings_EnableSOTFLabel}" ToolTip="{DynamicResource ServerSettings_EnableSOTFTooltip}" VerticalContentAlignment="Center" FontWeight="Bold" SourceUpdated="EnableSOTFCheckbox_SourceUpdated" />
<Button Margin="20,5,5,5" Click="HelpSOTF_Click" BorderThickness="0" Background="{StaticResource BeigeGradient}" ToolTip="{DynamicResource ServerSettings_SOTF_HelpTooltip}" Style="{StaticResource ButtonStyle1}">
<Image Source="{com:Icon Path=/Ark Server Manager;component/Art/Help.ico,Size=32}"/>
</Button>
</StackPanel>
</GroupBox.Header>

View file

@ -658,22 +658,9 @@ namespace ServerManagerTool
window.Focus();
}
private void HelpSOTF_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(Config.Default.AppUrl_SotF))
return;
Process.Start(Config.Default.AppUrl_SotF);
}
private void PatchNotes_Click(object sender, RoutedEventArgs e)
{
var url = string.Empty;
if (Settings.SOTF_Enabled)
url =Config.Default.AppPatchNotesUrlSotF;
else
url = Config.Default.AppPatchNotesUrl;
var url = Settings.SOTF_Enabled ? Config.Default.AppPatchNotesUrlSotF : Config.Default.AppPatchNotesUrl;
if (string.IsNullOrWhiteSpace(url))
return;
@ -812,10 +799,8 @@ namespace ServerManagerTool
}
// <data folder>\SteamCMD\steamapps\workshop\content\<app id>
if (this.Settings.SOTF_Enabled)
folder = Path.Combine(Config.Default.DataDir, Config.Default.SteamCmdDir, Config.Default.AppSteamWorkshopFolderRelativePath_SotF);
else
folder = Path.Combine(Config.Default.DataDir, Config.Default.SteamCmdDir, Config.Default.AppSteamWorkshopFolderRelativePath);
var workshopPath = string.Format(Config.Default.AppSteamWorkshopFolderRelativePath, this.Settings.SOTF_Enabled ? Config.Default.AppId_SotF : Config.Default.AppId);
folder = Path.Combine(Config.Default.DataDir, Config.Default.SteamCmdDir, workshopPath);
if (Directory.Exists(folder))
{
foreach (var modFolder in Directory.GetDirectories(folder))

View file

@ -160,7 +160,7 @@ namespace ServerManagerTool.Utils
return timespan.TotalSeconds;
}
public static string GetLatestModCacheTimeFile(string modId, bool isSotF) => IOUtils.NormalizePath(Path.Combine(GetModCachePath(modId, isSotF), Config.Default.LastUpdatedTimeFile));
public static string GetLatestModCacheTimeFile(string modId, string appId) => IOUtils.NormalizePath(Path.Combine(GetModCachePath(modId, appId), Config.Default.LastUpdatedTimeFile));
public static string GetLatestModTimeFile(string installDirectory, string modId) => IOUtils.NormalizePath(Path.Combine(installDirectory, Config.Default.ServerModsRelativePath, modId, Config.Default.LastUpdatedTimeFile));
@ -228,12 +228,10 @@ namespace ServerManagerTool.Utils
return mapNames != null && mapNames.Count > 0 ? mapNames[0] : string.Empty;
}
public static string GetModCachePath(string modId, bool isSotF)
public static string GetModCachePath(string modId, string appId)
{
if (isSotF)
return IOUtils.NormalizePath(Path.Combine(Config.Default.DataDir, Config.Default.SteamCmdDir, Config.Default.AppSteamWorkshopFolderRelativePath_SotF, modId));
return IOUtils.NormalizePath(Path.Combine(Config.Default.DataDir, Config.Default.SteamCmdDir, Config.Default.AppSteamWorkshopFolderRelativePath, modId));
var workshopPath = string.Format(Config.Default.AppSteamWorkshopFolderRelativePath, appId);
return IOUtils.NormalizePath(Path.Combine(Config.Default.DataDir, Config.Default.SteamCmdDir, workshopPath, modId));
}
public static List<string> GetModIdList(string modIds)
@ -272,27 +270,21 @@ namespace ServerManagerTool.Utils
var modFolder = GetModPath(installDirectory, modId);
var modFile = $"{modFolder}.mod";
Dictionary<string, string> metaInformation;
List<string> mapNames;
ReadModFile(modFile, out modId, out metaInformation, out mapNames);
ReadModFile(modFile, out _, out Dictionary<string, string> metaInformation, out _);
return metaInformation != null && metaInformation.ContainsKey("ModType") ? metaInformation["ModType"] : MODTYPE_UNKNOWN;
}
public static string GetSteamManifestFile(string installDirectory, bool isSotF)
public static string GetSteamManifestFile(string installDirectory, string appIdServer)
{
if (isSotF)
return IOUtils.NormalizePath(Path.Combine(installDirectory, Config.Default.SteamManifestFolderRelativePath, Config.Default.AppSteamManifestFile_SotF));
return IOUtils.NormalizePath(Path.Combine(installDirectory, Config.Default.SteamManifestFolderRelativePath, Config.Default.AppSteamManifestFile));
var fileName = string.Format(Config.Default.AppSteamManifestFile, appIdServer);
return IOUtils.NormalizePath(Path.Combine(installDirectory, Config.Default.SteamManifestFolderRelativePath, fileName));
}
public static string GetSteamWorkshopFile(bool isSotF)
public static string GetSteamWorkshopFile(string appId)
{
if (isSotF)
return IOUtils.NormalizePath(Path.Combine(Config.Default.DataDir, Config.Default.SteamCmdDir, Config.Default.SteamWorkshopFolderRelativePath, Config.Default.AppSteamWorkshopFile_SotF));
return IOUtils.NormalizePath(Path.Combine(Config.Default.DataDir, Config.Default.SteamCmdDir, Config.Default.SteamWorkshopFolderRelativePath, Config.Default.AppSteamWorkshopFile));
var fileName = string.Format(Config.Default.AppSteamWorkshopFile, appId);
return IOUtils.NormalizePath(Path.Combine(Config.Default.DataDir, Config.Default.SteamCmdDir, Config.Default.SteamWorkshopFolderRelativePath, fileName));
}
public static int GetSteamWorkshopLatestTime(string workshopFile, string modId)

View file

@ -7,6 +7,29 @@
<link href="https://arkservermanager.freeforums.net/" />
<updated>2022-07-25T00:00:00Z</updated>
<entry>
<id>urn:uuid:84E1DDF9-EFA4-4A8B-90DE-564AE3B3B633</id>
<title>1.1.437 (1.1.437.1)</title>
<summary>1.1.437.1</summary>
<link href="" />
<updated>2022-08-07T00:00:00Z</updated>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, Verdana, Helvetica, Sans-Serif;font-size: .8em;">
<p>
<u style="font-size: .9em;">CHANGE</u>
<br/>
<ul>
<li>Server Update - updated the code to simplify which set of dedicated server files (Ark Survival Evolved or Ark: SotF) is required when performing server and mod file updates. Separate Cache folders will be maintained for each.</li>
</ul>
</p>
</div>
</content>
<author>
<name>bletch</name>
<email>bletch1971@hotmail.com</email>
</author>
</entry>
<entry>
<id>urn:uuid:8CDA70CF-E8B8-4B9B-AD50-AD9A8B528E5B</id>
<title>1.1.436 (1.1.436.4)</title>

View file

@ -5,96 +5,21 @@
<title>Ark Server Manager Version Feed</title>
<subtitle>This is the Ark Server Manager beta version feed.</subtitle>
<link href="https://arkservermanager.freeforums.net/" />
<updated>2022-07-25T00:00:00Z</updated>
<updated>2022-08-07T00:00:00Z</updated>
<entry>
<id>urn:uuid:8CDA70CF-E8B8-4B9B-AD50-AD9A8B528E5B</id>
<title>1.1.436 (1.1.436.4)</title>
<summary>1.1.436.4</summary>
<id>urn:uuid:84E1DDF9-EFA4-4A8B-90DE-564AE3B3B633</id>
<title>1.1.437 (1.1.437.1)</title>
<summary>1.1.437.1</summary>
<link href="" />
<updated>2022-07-25T00:00:00Z</updated>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, Verdana, Helvetica, Sans-Serif;font-size: .8em;">
<p>
<u style="font-size: .9em;">BUGFIX</u>
<br/>
<ul>
<li>Fixed a crash bug when trying to set the logging folder.</li>
</ul>
<u style="font-size: .9em;">CHANGE</u>
<br/>
<ul>
<li>zh-CN Translation file updated.</li>
</ul>
</p>
</div>
</content>
<author>
<name>bletch</name>
<email>bletch1971@hotmail.com</email>
</author>
</entry>
<entry>
<id>urn:uuid:8CDA70CF-E8B8-4B9B-AD50-AD9A8B528E5B</id>
<title>1.1.436 (1.1.436.3)</title>
<summary>1.1.436.3</summary>
<link href="" />
<updated>2022-07-21T00:00:00Z</updated>
<updated>2022-08-07T00:00:00Z</updated>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, Verdana, Helvetica, Sans-Serif;font-size: .8em;">
<p>
<u style="font-size: .9em;">CHANGE</u>
<br/>
<ul>
<li>ru-RU Translation file updated.</li>
<li>tr-TR Translation file updated.</li>
</ul>
</p>
</div>
</content>
<author>
<name>bletch</name>
<email>bletch1971@hotmail.com</email>
</author>
</entry>
<entry>
<id>urn:uuid:8CDA70CF-E8B8-4B9B-AD50-AD9A8B528E5B</id>
<title>1.1.436 (1.1.436.2)</title>
<summary>1.1.436.2</summary>
<link href="" />
<updated>2022-07-16T00:00:00Z</updated>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, Verdana, Helvetica, Sans-Serif;font-size: .8em;">
<p>
<u style="font-size: .9em;">BUGFIX</u>
<br/>
<ul>
<li>Added a check for a valid configuration file when starting the server manager.\r\nIf config file is not valid, then it will delete the config file and shutdown the manager, with a message to restart the manager.</li>
</ul>
</p>
</div>
</content>
<author>
<name>bletch</name>
<email>bletch1971@hotmail.com</email>
</author>
</entry>
<entry>
<id>urn:uuid:8CDA70CF-E8B8-4B9B-AD50-AD9A8B528E5B</id>
<title>1.1.436 (1.1.436.1)</title>
<summary>1.1.436.1</summary>
<link href="" />
<updated>2022-07-15T00:00:00Z</updated>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, Verdana, Helvetica, Sans-Serif;font-size: .8em;">
<p>
<u style="font-size: .9em;">BUGFIX</u>
<br/>
<ul>
<li>Server Status - changed the server status code to stop the status cycling and to be more accurate.</li>
<li>Server Update - updated the code to simplify which set of dedicated server files (Ark Survival Evolved or Ark: SotF) is required when performing server and mod file updates. Separate Cache folders will be maintained for each.</li>
</ul>
</p>
</div>

View file

@ -104,7 +104,7 @@ namespace ServerManagerTool
{
try
{
WorkshopFiles = await LoadWorkshopItemsAsync(_profile.SOTF_Enabled);
WorkshopFiles = await LoadWorkshopItemsAsync();
await LoadModsFromProfile();
}
catch (Exception ex)
@ -156,7 +156,7 @@ namespace ServerManagerTool
try
{
WorkshopFiles = await LoadWorkshopItemsAsync(_profile.SOTF_Enabled);
WorkshopFiles = await LoadWorkshopItemsAsync();
}
catch (Exception ex)
{
@ -506,12 +506,15 @@ namespace ServerManagerTool
ModDetailsChanged = true;
}
private async Task<WorkshopFileList> LoadWorkshopItemsAsync(bool isSotF)
private async Task<WorkshopFileList> LoadWorkshopItemsAsync()
{
WorkshopFileDetailResponse localCache = null;
var appId = _profile.SOTF_Enabled ? Config.Default.AppId_SotF : Config.Default.AppId;
var workshopCacheFile = string.Format(Config.Default.WorkshopCacheFile, appId);
await Task.Run(() => {
var file = Path.Combine(Config.Default.DataDir, isSotF ? Config.Default.WorkshopCacheFile_SotF : Config.Default.WorkshopCacheFile);
var file = Path.Combine(Config.Default.DataDir, workshopCacheFile);
// try to load the cache file.
localCache = WorkshopFileDetailResponse.Load(file);

View file

@ -25,7 +25,6 @@ namespace ServerManagerTool
private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
private readonly ServerProfile _profile = null;
private ModDetailList _modDetails = null;
private readonly bool _isSotF = false;
private readonly ModDetailsWindow _window = null;
@ -40,7 +39,6 @@ namespace ServerManagerTool
WindowUtils.RemoveDefaultResourceDictionary(this, Config.Default.DefaultGlobalizationFile);
_profile = profile;
_isSotF = _profile?.SOTF_Enabled ?? false;
this.Title = string.Format(_globalizer.GetResourceString("WorkshopFiles_ProfileTitle"), _profile?.ProfileName);
UpdateModDetailsList(modDetails);
@ -55,7 +53,6 @@ namespace ServerManagerTool
_window = window;
_profile = profile;
_isSotF = _profile?.SOTF_Enabled ?? false;
this.Title = string.Format(_globalizer.GetResourceString("WorkshopFiles_ProfileTitle"), _profile?.ProfileName);
UpdateModDetailsList(window?.ModDetails);
@ -164,8 +161,11 @@ namespace ServerManagerTool
WorkshopFileDetailResponse localCache = null;
WorkshopFileDetailResponse steamCache = null;
var appId = _profile.SOTF_Enabled ? Config.Default.AppId_SotF : Config.Default.AppId;
var workshopCacheFile = string.Format(Config.Default.WorkshopCacheFile, appId);
await Task.Run( () => {
var file = Path.Combine(Config.Default.DataDir, _isSotF ? Config.Default.WorkshopCacheFile_SotF : Config.Default.WorkshopCacheFile);
var file = Path.Combine(Config.Default.DataDir, workshopCacheFile);
// try to load the cache file.
localCache = WorkshopFileDetailResponse.Load(file);
@ -178,7 +178,7 @@ namespace ServerManagerTool
// check if the cache exists
if (steamCache == null)
{
steamCache = SteamUtils.GetSteamModDetails(_isSotF ? Config.Default.AppId_SotF : Config.Default.AppId);
steamCache = SteamUtils.GetSteamModDetails(appId);
if (steamCache != null)
steamCache.Save(file);
else

View file

@ -74,9 +74,6 @@
<setting name="AppPatchNotesUrl" serializeAs="String">
<value>https://forums.funcom.com/c/conan-exiles/Patch-Notes</value>
</setting>
<setting name="AppUrl" serializeAs="String">
<value>https://store.steampowered.com/app/440900/</value>
</setting>
<setting name="LastUpdatedTimeFile" serializeAs="String">
<value>LastUpdatedSM.txt</value>
</setting>
@ -87,7 +84,7 @@
<value>+login {0} +workshop_download_item {1} {2} +quit</value>
</setting>
<setting name="AppSteamWorkshopFolderRelativePath" serializeAs="String">
<value>steamapps\workshop\content\440900\</value>
<value>steamapps\workshop\content\{0}\</value>
</setting>
<setting name="ServerModsRelativePath" serializeAs="String">
<value>ConanSandbox\Mods</value>
@ -96,7 +93,7 @@
<value>ConanSandbox\Saved</value>
</setting>
<setting name="WorkshopCacheFile" serializeAs="String">
<value>workshopcache_440900.json</value>
<value>workshopcache_{0}.json</value>
</setting>
<setting name="SteamCmd_AnonymousUsername" serializeAs="String">
<value>anonymous</value>
@ -105,7 +102,7 @@
<value>steamapps\workshop</value>
</setting>
<setting name="AppSteamWorkshopFile" serializeAs="String">
<value>appworkshop_440900.acf</value>
<value>appworkshop_{0}.acf</value>
</setting>
<setting name="AppId" serializeAs="String">
<value>440900</value>
@ -219,7 +216,7 @@
<value>__</value>
</setting>
<setting name="AppSteamManifestFile" serializeAs="String">
<value>appmanifest_443030.acf</value>
<value>appmanifest_{0}.acf</value>
</setting>
<setting name="SteamManifestFolderRelativePath" serializeAs="String">
<value>steamapps</value>
@ -287,6 +284,15 @@
<setting name="ServicePointManager_SecurityProtocol" serializeAs="String">
<value>3072</value>
</setting>
<setting name="AppId_Testlive" serializeAs="String">
<value>931180</value>
</setting>
<setting name="AppIdServer_Testlive" serializeAs="String">
<value>931580</value>
</setting>
<setting name="AppPatchNotesUrl_Testlive" serializeAs="String">
<value>https://forums.funcom.com/c/conan-exiles/exiles-pc/testlive</value>
</setting>
</ServerManagerTool.Config>
<ServerManagerTool.Common.CommonConfig>
<setting name="DefaultSteamAPIKey" serializeAs="String">

View file

@ -273,15 +273,6 @@ namespace ServerManagerTool {
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("https://store.steampowered.com/app/440900/")]
public string AppUrl {
get {
return ((string)(this["AppUrl"]));
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
@ -421,7 +412,7 @@ namespace ServerManagerTool {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("steamapps\\workshop\\content\\440900\\")]
[global::System.Configuration.DefaultSettingValueAttribute("steamapps\\workshop\\content\\{0}\\")]
public string AppSteamWorkshopFolderRelativePath {
get {
return ((string)(this["AppSteamWorkshopFolderRelativePath"]));
@ -532,7 +523,7 @@ namespace ServerManagerTool {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("workshopcache_440900.json")]
[global::System.Configuration.DefaultSettingValueAttribute("workshopcache_{0}.json")]
public string WorkshopCacheFile {
get {
return ((string)(this["WorkshopCacheFile"]));
@ -703,7 +694,7 @@ namespace ServerManagerTool {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("appworkshop_440900.acf")]
[global::System.Configuration.DefaultSettingValueAttribute("appworkshop_{0}.acf")]
public string AppSteamWorkshopFile {
get {
return ((string)(this["AppSteamWorkshopFile"]));
@ -1485,7 +1476,7 @@ namespace ServerManagerTool {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("appmanifest_443030.acf")]
[global::System.Configuration.DefaultSettingValueAttribute("appmanifest_{0}.acf")]
public string AppSteamManifestFile {
get {
return ((string)(this["AppSteamManifestFile"]));
@ -2444,5 +2435,32 @@ namespace ServerManagerTool {
return ((int)(this["ServicePointManager_SecurityProtocol"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("931180")]
public string AppId_Testlive {
get {
return ((string)(this["AppId_Testlive"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("931580")]
public string AppIdServer_Testlive {
get {
return ((string)(this["AppIdServer_Testlive"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("https://forums.funcom.com/c/conan-exiles/exiles-pc/testlive")]
public string AppPatchNotesUrl_Testlive {
get {
return ((string)(this["AppPatchNotesUrl_Testlive"]));
}
}
}
}

View file

@ -77,9 +77,6 @@
<Setting Name="AppPatchNotesUrl" Type="System.String" Scope="Application">
<Value Profile="(Default)">https://forums.funcom.com/c/conan-exiles/Patch-Notes</Value>
</Setting>
<Setting Name="AppUrl" Type="System.String" Scope="Application">
<Value Profile="(Default)">https://store.steampowered.com/app/440900/</Value>
</Setting>
<Setting Name="RunAsAdministratorPrompt" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
@ -117,7 +114,7 @@
<Value Profile="(Default)">+login {0} +workshop_download_item {1} {2} +quit</Value>
</Setting>
<Setting Name="AppSteamWorkshopFolderRelativePath" Type="System.String" Scope="Application">
<Value Profile="(Default)">steamapps\workshop\content\440900\</Value>
<Value Profile="(Default)">steamapps\workshop\content\{0}\</Value>
</Setting>
<Setting Name="ServerModsRelativePath" Type="System.String" Scope="Application">
<Value Profile="(Default)">ConanSandbox\Mods</Value>
@ -147,7 +144,7 @@
<Value Profile="(Default)" />
</Setting>
<Setting Name="WorkshopCacheFile" Type="System.String" Scope="Application">
<Value Profile="(Default)">workshopcache_440900.json</Value>
<Value Profile="(Default)">workshopcache_{0}.json</Value>
</Setting>
<Setting Name="Email_Host" Type="System.String" Scope="User">
<Value Profile="(Default)" />
@ -192,7 +189,7 @@
<Value Profile="(Default)">steamapps\workshop</Value>
</Setting>
<Setting Name="AppSteamWorkshopFile" Type="System.String" Scope="Application">
<Value Profile="(Default)">appworkshop_440900.acf</Value>
<Value Profile="(Default)">appworkshop_{0}.acf</Value>
</Setting>
<Setting Name="SteamCmd_Password" Type="System.String" Scope="User">
<Value Profile="(Default)" />
@ -414,7 +411,7 @@
<Value Profile="(Default)">__</Value>
</Setting>
<Setting Name="AppSteamManifestFile" Type="System.String" Scope="Application">
<Value Profile="(Default)">appmanifest_443030.acf</Value>
<Value Profile="(Default)">appmanifest_{0}.acf</Value>
</Setting>
<Setting Name="SteamManifestFolderRelativePath" Type="System.String" Scope="Application">
<Value Profile="(Default)">steamapps</Value>
@ -671,5 +668,14 @@
<Setting Name="ServicePointManager_SecurityProtocol" Type="System.Int32" Scope="Application">
<Value Profile="(Default)">3072</Value>
</Setting>
<Setting Name="AppId_Testlive" Type="System.String" Scope="Application">
<Value Profile="(Default)">931180</Value>
</Setting>
<Setting Name="AppIdServer_Testlive" Type="System.String" Scope="Application">
<Value Profile="(Default)">931580</Value>
</Setting>
<Setting Name="AppPatchNotesUrl_Testlive" Type="System.String" Scope="Application">
<Value Profile="(Default)">https://forums.funcom.com/c/conan-exiles/exiles-pc/testlive</Value>
</Setting>
</Settings>
</SettingsFile>

View file

@ -1276,6 +1276,9 @@
<!--#region Server Settings - Server Details -->
<sys:String x:Key="ServerSettings_ServerDetailsLabel">Server Details</sys:String>
<sys:String x:Key="ServerSettings_UseTestliveLabel">Use Testlive Dedicated Server Files</sys:String>
<sys:String x:Key="ServerSettings_UseTestliveTooltip">If enabled, will use the testlive dedicated server files instead of the testlive branch. Leave the branch as default, do not set to Testlive.</sys:String>
<sys:String x:Key="ServerSettings_BranchLabel">Branch Details</sys:String>
<sys:String x:Key="ServerSettings_BranchNameLabel">Branch Name:</sys:String>
<sys:String x:Key="ServerSettings_BranchNameTooltip">The name of the branch to download (leave blank to use the release branch).</sys:String>

View file

@ -9,6 +9,7 @@ namespace ServerManagerTool.Lib
{
}
public string AppIdServer = string.Empty;
public string BranchName = string.Empty;
public string BranchPassword = string.Empty;
@ -16,6 +17,7 @@ namespace ServerManagerTool.Lib
{
return new BranchSnapshot
{
AppIdServer = profile.UseTestlive ? Config.Default.AppIdServer_Testlive : string.Empty,
BranchName = profile.BranchName,
BranchPassword = profile.BranchPassword
};
@ -25,6 +27,7 @@ namespace ServerManagerTool.Lib
{
return new BranchSnapshot
{
AppIdServer = profile.AppIdServer,
BranchName = profile.BranchName,
BranchPassword = profile.BranchPassword
};
@ -42,17 +45,20 @@ namespace ServerManagerTool.Lib
if (x is null || y is null)
return false;
//Check whether the snapshot' properties are equal.
return string.Equals(x.BranchName ?? string.Empty, y.BranchName ?? string.Empty, StringComparison.OrdinalIgnoreCase);
//Check whether the snapshot properties are equal.
var result = string.Equals(x.AppIdServer ?? string.Empty, y.AppIdServer ?? string.Empty, StringComparison.OrdinalIgnoreCase);
return result && string.Equals(x.BranchName ?? string.Empty, y.BranchName ?? string.Empty, StringComparison.OrdinalIgnoreCase);
}
public int GetHashCode(BranchSnapshot snapshot)
{
//Check whether the object is null
if (snapshot is null) return 0;
if (snapshot is null)
return 0;
//Get hash code for the Name field if it is not null.
return snapshot.BranchName == null ? 0 : snapshot.BranchName.GetHashCode();
var result = $"{snapshot.AppIdServer ?? ""}-{snapshot.BranchName ?? ""}";
return result.GetHashCode();
}
}
}

View file

@ -787,7 +787,7 @@ namespace ServerManagerTool.Lib
}
}
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, _profile.InstallDirectory, Config.Default.AppIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, _profile.InstallDirectory, _profile.AppIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
if (steamCmdRemoveQuit)
{
SteamCMDProcessWindowStyle = ProcessWindowStyle.Normal;
@ -882,8 +882,8 @@ namespace ServerManagerTool.Lib
LogProfileMessage($"{modDetail.title}.\r\n");
}
var modCachePath = ModUtils.GetModCachePath(modId);
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId);
var modCachePath = ModUtils.GetModCachePath(modId, _profile.AppId);
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, _profile.AppId);
var modPath = ModUtils.GetModPath(_profile.InstallDirectory, modId);
var modTimeFile = ModUtils.GetLatestModTimeFile(_profile.InstallDirectory, modId);
@ -963,13 +963,9 @@ namespace ServerManagerTool.Lib
steamCmdArgs = string.Empty;
if (Config.Default.SteamCmd_UseAnonymousCredentials)
{
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_AnonymousUsername, Config.Default.AppId, modId);
}
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_AnonymousUsername, _profile.AppId, modId);
else
{
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_Username, Config.Default.AppId, modId);
}
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_Username, _profile.AppId, modId);
modSuccess = ServerUpdater.UpgradeModsAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, Config.Default.SteamCmdRedirectOutput ? modOutputHandler : null, cancellationToken, SteamCMDProcessWindowStyle).Result;
if (modSuccess && downloadSuccessful)
@ -988,7 +984,7 @@ namespace ServerManagerTool.Lib
if (modDetail == null || modDetail.time_updated <= 0)
{
// get the version number from the steamcmd workshop file.
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(), modId).ToString();
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(_profile.AppId), modId).ToString();
}
// update the last updated file with the steam updated time.
@ -1156,26 +1152,32 @@ namespace ServerManagerTool.Lib
LogProfileMessage("Started server update...");
LogProfileMessage("------------------------");
LogProfileMessage($"Server Manager version: {App.Instance.Version}");
LogProfileMessage($"Server branch: {GetBranchName(_profile.BranchName)}");
LogProfileMessage($"Server branch: {GetBranchInfo(_profile.AppIdServer, _profile.BranchName)}");
LogProfileMessage($"Profile Name: {_profile.ProfileName}");
// check if the server needs to be updated
var serverCacheLastUpdated = GetServerLatestTime(GetServerCacheTimeFile(_profile?.BranchName));
var serverCacheLastUpdated = GetServerLatestTime(GetServerCacheTimeFile(_profile.AppIdServer, _profile.BranchName));
var serverLastUpdated = GetServerLatestTime(GetServerTimeFile());
var updateServer = serverCacheLastUpdated > serverLastUpdated;
// check if any of the mods need to be updated
var updateModIds = new List<string>();
var modIdList = GetModList();
var appModList = GetModList();
// cycle through each mod.
foreach (var modId in modIdList)
foreach (var appMods in appModList)
{
// check if the mod needs to be updated.
var modCacheLastUpdated = ModUtils.GetModLatestTime(ModUtils.GetLatestModCacheTimeFile(modId));
var modLastUpdated = ModUtils.GetModLatestTime(ModUtils.GetLatestModTimeFile(_profile.InstallDirectory, modId));
if (modCacheLastUpdated > modLastUpdated || modLastUpdated == 0)
updateModIds.Add(modId);
if (!appMods.AppId.Equals(_profile.AppId, StringComparison.OrdinalIgnoreCase))
continue;
foreach (var modId in appMods.ModIdList)
{
// check if the mod needs to be updated.
var modCacheLastUpdated = ModUtils.GetModLatestTime(ModUtils.GetLatestModCacheTimeFile(modId, _profile.AppId));
var modLastUpdated = ModUtils.GetModLatestTime(ModUtils.GetLatestModTimeFile(_profile.InstallDirectory, modId));
if (modCacheLastUpdated > modLastUpdated || modLastUpdated == 0)
updateModIds.Add(modId);
}
}
if (ExitCode != EXITCODE_NORMALEXIT)
@ -1272,7 +1274,7 @@ namespace ServerManagerTool.Lib
try
{
var cacheFolder = GetServerCacheFolder(_profile?.BranchName);
var cacheFolder = GetServerCacheFolder(_profile?.AppIdServer, _profile?.BranchName);
if (Directory.Exists(cacheFolder))
{
@ -1293,14 +1295,14 @@ namespace ServerManagerTool.Lib
_profile.LastInstalledVersion = GetServerVersion(GetServerVersionFile()).ToString();
LogProfileMessage("Updated server from cache. See patch notes.");
LogProfileMessage(Config.Default.AppPatchNotesUrl);
LogProfileMessage(_profile.UseTestlive ? Config.Default.AppPatchNotesUrl_Testlive : Config.Default.AppPatchNotesUrl);
if (!string.IsNullOrWhiteSpace(Config.Default.Alert_ServerUpdate))
alertMessage.AppendLine(Config.Default.Alert_ServerUpdate);
emailMessage.AppendLine();
emailMessage.AppendLine("Updated server from cache. See patch notes.");
emailMessage.AppendLine(Config.Default.AppPatchNotesUrl);
emailMessage.AppendLine(_profile.UseTestlive ? Config.Default.AppPatchNotesUrl_Testlive : Config.Default.AppPatchNotesUrl);
_profile.ServerUpdated = true;
}
@ -1346,7 +1348,7 @@ namespace ServerManagerTool.Lib
for (var index = 0; index < updateModIds.Count; index++)
{
var modId = updateModIds[index];
var modCachePath = ModUtils.GetModCachePath(modId);
var modCachePath = ModUtils.GetModCachePath(modId, _profile.AppId);
var modPath = ModUtils.GetModPath(_profile.InstallDirectory, modId);
var modName = modDetails?.publishedfiledetails?.FirstOrDefault(m => m.publishedfileid == modId)?.title ?? string.Empty;
@ -1431,7 +1433,7 @@ namespace ServerManagerTool.Lib
}
else
{
if (modIdList.Count > 0)
if (appModList.Sum(m => m.ModIdList.Count) > 0)
LogProfileMessage("Mods are already up to date, no updates required.");
}
@ -1464,7 +1466,7 @@ namespace ServerManagerTool.Lib
else
{
LogProfileMessage("");
if (modIdList.Count > 0)
if (appModList.Sum(m => m.ModIdList.Count) > 0)
LogProfileMessage("The server and mods files are already up to date, no updates required.");
else
LogProfileMessage("The server files are already up to date, no updates required.");
@ -1500,10 +1502,10 @@ namespace ServerManagerTool.Lib
private void UpdateModCache()
{
// get a list of mods to be processed
var modIdList = GetModList();
var appModList = GetModList();
// check if there are any mods to be processed
if (modIdList.Count == 0)
if (appModList.Count == 0 || appModList.Sum(m => m.ModIdList.Count) == 0)
{
ExitCode = EXITCODE_NORMALEXIT;
return;
@ -1515,12 +1517,13 @@ namespace ServerManagerTool.Lib
LogMessage("----------------------------");
LogMessage($"Server Manager version: {App.Instance.Version}");
LogMessage($"Downloading mod information for {modIdList.Count} mods from steam.");
var totalMods = appModList.Sum(m => m.ModIdList.Count);
LogMessage($"Downloading mod information for {totalMods} mods from steam.");
var forceUpdateMods = Config.Default.ServerUpdate_ForceUpdateModsIfNoSteamInfo || string.IsNullOrWhiteSpace(SteamUtils.SteamWebApiKey);
// get the details of the mods to be processed.
var modDetails = SteamUtils.GetSteamModDetails(modIdList);
var modDetails = SteamUtils.GetSteamModDetails(appModList);
if (modDetails == null)
{
if (forceUpdateMods)
@ -1538,19 +1541,19 @@ namespace ServerManagerTool.Lib
}
else
{
LogMessage($"Downloaded mod information for {modIdList.Count} mods from steam.");
LogMessage($"Downloaded mod information for {totalMods} mods from steam.");
LogMessage("");
}
// cycle through each mod finding which needs to be updated.
var updateModIds = new List<string>();
var updateMods = new List<(string AppId, List<string> ModIdList)>();
if (modDetails == null)
{
if (forceUpdateMods)
{
LogMessage("All mods will be updated - unable to download steam information and force mod update is TRUE.");
updateModIds.AddRange(modIdList);
updateMods = appModList;
modDetails = new PublishedFileDetailsResponse();
}
}
@ -1559,46 +1562,67 @@ namespace ServerManagerTool.Lib
if (Config.Default.ServerUpdate_ForceUpdateMods)
{
LogMessage("All mods will be updated - force mod update is TRUE.");
updateModIds.AddRange(modIdList);
updateMods = appModList;
}
else
{
LogMessage("Mods will be selectively updated - force mod update is FALSE.");
foreach (var modId in modIdList)
foreach (var appMod in appModList)
{
var modDetail = modDetails.publishedfiledetails?.FirstOrDefault(m => m.publishedfileid.Equals(modId, StringComparison.OrdinalIgnoreCase));
if (modDetail == null)
foreach (var modId in appMod.ModIdList)
{
LogMessage($"Mod {modId} will not be updated - unable to download steam information.");
continue;
}
if (modDetail.time_updated == 0)
{
LogMessage($"Mod {modId} will be updated - mod is private.");
updateModIds.Add(modId);
}
else
{
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId);
// check if the mod needs to be updated
var steamLastUpdated = modDetail.time_updated;
var modCacheLastUpdated = ModUtils.GetModLatestTime(cacheTimeFile);
if (steamLastUpdated > modCacheLastUpdated)
var modDetail = modDetails.publishedfiledetails?.FirstOrDefault(m => m.publishedfileid.Equals(modId, StringComparison.OrdinalIgnoreCase));
if (modDetail == null)
{
LogMessage($"Mod {modId} will be updated - new version found.");
updateModIds.Add(modId);
LogMessage($"Mod {modId} will not be updated - unable to download steam information.");
continue;
}
else if (modCacheLastUpdated == 0)
var updateMod = updateMods.FirstOrDefault(m => m.AppId.Equals(appMod.AppId, StringComparison.OrdinalIgnoreCase));
if (modDetail.time_updated == 0)
{
LogMessage($"Mod {modId} will be updated - cache not versioned.");
updateModIds.Add(modId);
LogMessage($"Mod {modId} will be updated - mod is private.");
if (updateMod == default)
updateMods.Add((appMod.AppId, new List<string> { modId }));
else
updateMod.ModIdList.Add(modId);
}
else
{
LogMessage($"Mod {modId} update skipped - cache contains the latest version.");
if (modDetail.creator_app_id is null || modDetail.creator_app_id.Equals(appMod.AppId, StringComparison.OrdinalIgnoreCase))
{
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, appMod.AppId);
// check if the mod needs to be updated
var steamLastUpdated = modDetail.time_updated;
var modCacheLastUpdated = ModUtils.GetModLatestTime(cacheTimeFile);
if (steamLastUpdated > modCacheLastUpdated)
{
LogMessage($"Mod {modId} will be updated - new version found.");
if (updateMod == default)
updateMods.Add((appMod.AppId, new List<string> { modId }));
else
updateMod.ModIdList.Add(modId);
}
else if (modCacheLastUpdated == 0)
{
LogMessage($"Mod {modId} will be updated - cache not versioned.");
if (updateMod == default)
updateMods.Add((appMod.AppId, new List<string> { modId }));
else
updateMod.ModIdList.Add(modId);
}
else
{
LogMessage($"Mod {modId} update skipped - cache contains the latest version.");
}
}
else
{
LogMessage($"Mod {modId} update skipped - mod does not belong to this application.");
}
}
}
}
@ -1613,97 +1637,105 @@ namespace ServerManagerTool.Lib
return;
}
var totalUpdateMods = updateMods.Sum(m => m.ModIdList.Count);
var updateIndex = 0;
// cycle through each mod id.
for (var index = 0; index < updateModIds.Count; index++)
foreach (var appMod in updateMods)
{
var modId = updateModIds[index];
var modDetail = modDetails.publishedfiledetails?.FirstOrDefault(m => m.publishedfileid.Equals(modId, StringComparison.OrdinalIgnoreCase));
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId);
var modCachePath = ModUtils.GetModCachePath(modId);
var downloadSuccessful = false;
DataReceivedEventHandler modOutputHandler = (s, e) =>
for (var index = 0; index < appMod.ModIdList.Count; index++)
{
var dataValue = e.Data ?? string.Empty;
LogMessage(dataValue);
if (dataValue.StartsWith("Success."))
var modId = appMod.ModIdList[index];
var modDetail = modDetails.publishedfiledetails?.FirstOrDefault(m => m.publishedfileid.Equals(modId, StringComparison.OrdinalIgnoreCase));
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, appMod.AppId);
var modCachePath = ModUtils.GetModCachePath(modId, appMod.AppId);
var downloadSuccessful = false;
DataReceivedEventHandler modOutputHandler = (s, e) =>
{
downloadSuccessful = true;
}
};
LogMessage("");
LogMessage($"Started mod cache update {index + 1} of {updateModIds.Count}");
LogMessage($"{modId} - {modDetail?.title ?? "<unknown>"}");
var attempt = 0;
while (true)
{
attempt++;
downloadSuccessful = !Config.Default.SteamCmdRedirectOutput;
// update the mod cache
var steamCmdArgs = string.Empty;
if (Config.Default.SteamCmd_UseAnonymousCredentials)
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_AnonymousUsername, Config.Default.AppId, modId);
else
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_Username, Config.Default.AppId, modId);
var workingDirectory = Config.Default.DataPath;
var success = ServerUpdater.UpgradeModsAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, Config.Default.SteamCmdRedirectOutput ? modOutputHandler : null, CancellationToken.None, SteamCMDProcessWindowStyle).Result;
if (success && downloadSuccessful)
// download was successful, exit loop and continue.
break;
// download was not successful, log a failed attempt.
var logError = $"Mod {modId} cache update failed";
if (Config.Default.AutoUpdate_RetryOnFail)
logError += $" - attempt {attempt}.";
LogError(logError);
// check if we have reached the max failed attempt limit.
if (!Config.Default.AutoUpdate_RetryOnFail || attempt >= MAXRETRIES_STEAM)
{
// failed max limit reached
if (Config.Default.SteamCmdRedirectOutput)
var dataValue = e.Data ?? string.Empty;
LogMessage(dataValue);
if (dataValue.StartsWith("Success."))
{
LogMessage("Check steamcmd logs for more information why the mod cache update failed.\r\n");
LogMessage($"If the mod cache update keeps failing try disabling the '{_globalizer.GetResourceString("GlobalSettings_SteamCmdRedirectOutputLabel")}' option in the Server Manager settings window.");
downloadSuccessful = true;
}
};
updateIndex++;
LogMessage("");
LogMessage($"Started mod cache update {updateIndex} of {totalUpdateMods}");
LogMessage($"{modId} - {modDetail?.title ?? "<unknown>"}");
var attempt = 0;
while (true)
{
attempt++;
downloadSuccessful = !Config.Default.SteamCmdRedirectOutput;
// update the mod cache
var steamCmdArgs = string.Empty;
if (Config.Default.SteamCmd_UseAnonymousCredentials)
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_AnonymousUsername, appMod.AppId, modId);
else
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_Username, appMod.AppId, modId);
var workingDirectory = Config.Default.DataPath;
var success = ServerUpdater.UpgradeModsAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, Config.Default.SteamCmdRedirectOutput ? modOutputHandler : null, CancellationToken.None, SteamCMDProcessWindowStyle).Result;
if (success && downloadSuccessful)
// download was successful, exit loop and continue.
break;
// download was not successful, log a failed attempt.
var logError = $"Mod {modId} cache update failed";
if (Config.Default.AutoUpdate_RetryOnFail)
logError += $" - attempt {attempt}.";
LogError(logError);
// check if we have reached the max failed attempt limit.
if (!Config.Default.AutoUpdate_RetryOnFail || attempt >= MAXRETRIES_STEAM)
{
// failed max limit reached
if (Config.Default.SteamCmdRedirectOutput)
{
LogMessage("Check steamcmd logs for more information why the mod cache update failed.\r\n");
LogMessage($"If the mod cache update keeps failing try disabling the '{_globalizer.GetResourceString("GlobalSettings_SteamCmdRedirectOutputLabel")}' option in the Server Manager settings window.");
}
ExitCode = EXITCODE_CACHEMODUPDATEFAILED;
return;
}
ExitCode = EXITCODE_CACHEMODUPDATEFAILED;
return;
Task.Delay(5000).Wait();
}
Task.Delay(5000).Wait();
}
// check if any of the mod files have changed.
if (Directory.Exists(modCachePath))
{
var gotNewVersion = new DirectoryInfo(modCachePath).GetFiles("*.*", SearchOption.AllDirectories).Any(file => file.LastWriteTime >= _startTime);
if (gotNewVersion)
LogMessage("***** New version downloaded. *****");
else
LogMessage("No new version.");
var steamLastUpdated = modDetail?.time_updated.ToString() ?? string.Empty;
if (modDetail == null || modDetail.time_updated <= 0)
// check if any of the mod files have changed.
if (Directory.Exists(modCachePath))
{
// get the version number from the steamcmd workshop file.
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(), modId).ToString();
var gotNewVersion = new DirectoryInfo(modCachePath).GetFiles("*.*", SearchOption.AllDirectories).Any(file => file.LastWriteTime >= _startTime);
if (gotNewVersion)
LogMessage("***** New version downloaded. *****");
else
LogMessage("No new version.");
var steamLastUpdated = modDetail?.time_updated.ToString() ?? string.Empty;
if (modDetail == null || modDetail.time_updated <= 0)
{
// get the version number from the steamcmd workshop file.
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(appMod.AppId), modId).ToString();
}
File.WriteAllText(cacheTimeFile, steamLastUpdated);
LogMessage($"Mod {modId} cache version: {steamLastUpdated}");
}
else
LogMessage($"Mod {modId} cache does not exist.");
File.WriteAllText(cacheTimeFile, steamLastUpdated);
LogMessage($"Mod {modId} cache version: {steamLastUpdated}");
LogMessage($"Finished mod {modId} cache update.");
}
else
LogMessage($"Mod {modId} cache does not exist.");
LogMessage($"Finished mod {modId} cache update.");
}
LogMessage("---------------------------");
@ -1713,13 +1745,13 @@ namespace ServerManagerTool.Lib
ExitCode = EXITCODE_NORMALEXIT;
}
private void UpdateServerCache(string branchName, string branchPassword)
private void UpdateServerCache(string appIdServer, string branchName, string branchPassword)
{
LogBranchMessage(branchName, "-------------------------------");
LogBranchMessage(branchName, "Starting server cache update...");
LogBranchMessage(branchName, "-------------------------------");
LogBranchMessage(branchName, $"Server Manager version: {App.Instance.Version}");
LogBranchMessage(branchName, $"Server branch: {GetBranchName(branchName)}");
LogBranchMessage(appIdServer, branchName, "-------------------------------");
LogBranchMessage(appIdServer, branchName, "Starting server cache update...");
LogBranchMessage(appIdServer, branchName, "-------------------------------");
LogBranchMessage(appIdServer, branchName, $"Server Manager version: {App.Instance.Version}");
LogBranchMessage(appIdServer, branchName, $"Server branch: {GetBranchInfo(appIdServer, branchName)}");
var gotNewVersion = false;
var downloadSuccessful = false;
@ -1727,7 +1759,7 @@ namespace ServerManagerTool.Lib
var steamCmdFile = SteamCmdUpdater.GetSteamCmdFile(Config.Default.DataPath);
if (string.IsNullOrWhiteSpace(steamCmdFile) || !File.Exists(steamCmdFile))
{
LogBranchError(branchName, $"SteamCMD could not be found. Expected location is {steamCmdFile}");
LogBranchError(appIdServer, branchName, $"SteamCMD could not be found. Expected location is {steamCmdFile}");
ExitCode = EXITCODE_STEAMCMDNOTFOUND;
return;
}
@ -1735,7 +1767,7 @@ namespace ServerManagerTool.Lib
DataReceivedEventHandler serverOutputHandler = (s, e) =>
{
var dataValue = e.Data ?? string.Empty;
LogBranchMessage(branchName, dataValue);
LogBranchMessage(appIdServer, branchName, dataValue);
if (!gotNewVersion && dataValue.Contains("downloading,"))
{
gotNewVersion = true;
@ -1758,9 +1790,9 @@ namespace ServerManagerTool.Lib
}
}
var cacheFolder = GetServerCacheFolder(branchName);
var cacheFolder = GetServerCacheFolder(appIdServer, branchName);
LogBranchMessage(branchName, "Server update started.");
LogBranchMessage(appIdServer, branchName, "Server update started.");
var attempt = 0;
while (true)
@ -1771,7 +1803,7 @@ namespace ServerManagerTool.Lib
// update the server cache
var validate = Config.Default.AutoUpdate_ValidateServerFiles;
var steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, cacheFolder, Config.Default.AppIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
var steamCmdArgs = SteamUtils.BuildSteamCmdArguments(false, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, cacheFolder, appIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
var workingDirectory = Config.Default.DataPath;
var success = ServerUpdater.UpgradeServerAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, cacheFolder, Config.Default.SteamCmdRedirectOutput ? serverOutputHandler : null, CancellationToken.None, SteamCMDProcessWindowStyle).Result;
@ -1783,7 +1815,7 @@ namespace ServerManagerTool.Lib
var logError = "Server cache update failed";
if (Config.Default.AutoUpdate_RetryOnFail)
logError += $" - attempt {attempt}.";
LogBranchError(branchName, logError);
LogBranchError(appIdServer, branchName, logError);
// check if we have reached the max failed attempt limit.
if (!Config.Default.AutoUpdate_RetryOnFail || attempt >= MAXRETRIES_STEAM)
@ -1791,8 +1823,8 @@ namespace ServerManagerTool.Lib
// failed max limit reached
if (Config.Default.SteamCmdRedirectOutput)
{
LogBranchMessage(branchName, $"Check steamcmd logs for more information why the server cache update failed.\r\n");
LogBranchMessage(branchName, $"If the server cache update keeps failing try disabling the '{_globalizer.GetResourceString("GlobalSettings_SteamCmdRedirectOutputLabel")}' option in the ASM settings window.");
LogBranchMessage(appIdServer, branchName, $"Check steamcmd logs for more information why the server cache update failed.\r\n");
LogBranchMessage(appIdServer, branchName, $"If the server cache update keeps failing try disabling the '{_globalizer.GetResourceString("GlobalSettings_SteamCmdRedirectOutputLabel")}' option in the server manager settings window.");
}
ExitCode = EXITCODE_CACHESERVERUPDATEFAILED;
@ -1810,24 +1842,24 @@ namespace ServerManagerTool.Lib
if (gotNewVersion)
{
LogBranchMessage(branchName, "***** New version downloaded. *****");
LogBranchMessage(appIdServer, branchName, "***** New version downloaded. *****");
var latestCacheTimeFile = GetServerCacheTimeFile(branchName);
var latestCacheTimeFile = GetServerCacheTimeFile(appIdServer, branchName);
File.WriteAllText(latestCacheTimeFile, _startTime.ToString("o", CultureInfo.CurrentCulture));
}
else
LogBranchMessage(branchName, "No new version.");
LogBranchMessage(appIdServer, branchName, "No new version.");
}
else
LogBranchMessage(branchName, $"Server cache does not exist.");
LogBranchMessage(appIdServer, branchName, $"Server cache does not exist.");
var cacheVersion = GetServerVersion(GetServerCacheVersionFile(branchName)).ToString();
LogBranchMessage(branchName, $"Server cache version: {cacheVersion}");
var cacheVersion = GetServerVersion(GetServerCacheVersionFile(appIdServer, branchName)).ToString();
LogBranchMessage(appIdServer, branchName, $"Server cache version: {cacheVersion}");
LogBranchMessage(branchName, "-----------------------------");
LogBranchMessage(branchName, "Finished server cache update.");
LogBranchMessage(branchName, "-----------------------------");
LogBranchMessage(branchName, "");
LogBranchMessage(appIdServer, branchName, "-----------------------------");
LogBranchMessage(appIdServer, branchName, "Finished server cache update.");
LogBranchMessage(appIdServer, branchName, "-----------------------------");
LogBranchMessage(appIdServer, branchName, "");
ExitCode = EXITCODE_NORMALEXIT;
}
@ -2207,7 +2239,14 @@ namespace ServerManagerTool.Lib
}
}
public static string GetBranchName(string branchName) => string.IsNullOrWhiteSpace(branchName) ? Config.Default.DefaultServerBranchName : branchName;
public static string GetBranchInfo(string appIdServer, string branchName)
{
var branchInfo = string.IsNullOrWhiteSpace(branchName) ? Config.Default.DefaultServerBranchName : branchName;
if (!string.IsNullOrWhiteSpace(appIdServer) && !appIdServer.Equals(Config.Default.AppIdServer, StringComparison.OrdinalIgnoreCase))
branchInfo += $"_{appIdServer}";
return branchInfo;
}
private string GetLauncherFile() => IOUtils.NormalizePath(Path.Combine(GetProfileServerConfigDir(_profile), Config.Default.LauncherFile));
@ -2254,9 +2293,9 @@ namespace ServerManagerTool.Lib
return LogManager.GetLogger(loggerName);
}
private List<string> GetModList()
private List<(string AppId, List<string> ModIdList)> GetModList()
{
var modIdList = new List<string>();
var appMods = new List<(string AppId, List<string> ModIdList)>();
// check if we need to update the mods.
if (Config.Default.ServerUpdate_UpdateModsWhenUpdatingServer)
@ -2270,17 +2309,36 @@ namespace ServerManagerTool.Lib
if (!profile.EnableAutoUpdate)
continue;
var modIdList = new List<string>();
modIdList.AddRange(profile.ServerModIds);
var appMod = appMods.FirstOrDefault(m => m.AppId.Equals(profile.AppId, StringComparison.OrdinalIgnoreCase));
if (appMod == default)
appMods.Add((profile.AppId, modIdList));
else
appMod.ModIdList.AddRange(modIdList);
}
}
else
{
// get all the mods for only the specified profile.
var modIdList = new List<string>();
modIdList.AddRange(_profile.ServerModIds);
appMods.Add((_profile.AppId, modIdList));
}
}
return ModUtils.ValidateModList(modIdList);
for (int i = 0; i < appMods.Count; i++)
{
var validatedModList = ModUtils.ValidateModList(appMods[i].ModIdList);
appMods[i].ModIdList.Clear();
appMods[i].ModIdList.AddRange(validatedModList);
}
return appMods;
}
public static string GetMutexName(string directory)
@ -2337,11 +2395,15 @@ namespace ServerManagerTool.Lib
return IOUtils.NormalizePath(Path.Combine(Config.Default.BackupPath, Config.Default.ServersInstallPath, profile.ProfileId.ToLower()));
}
private static string GetServerCacheFolder(string branchName) => IOUtils.NormalizePath(Path.Combine(Config.Default.AutoUpdate_CacheDir, $"{Config.Default.ServerBranchFolderPrefix}{GetBranchName(branchName)}"));
public static string GetServerCacheFolder(string appIdServer, string branchName)
{
var branchInfo = GetBranchInfo(appIdServer, branchName) ?? "unknown";
return IOUtils.NormalizePath(Path.Combine(Config.Default.AutoUpdate_CacheDir, $"{Config.Default.ServerBranchFolderPrefix}{branchInfo}"));
}
private static string GetServerCacheTimeFile(string branchName) => IOUtils.NormalizePath(Path.Combine(GetServerCacheFolder(branchName), Config.Default.LastUpdatedTimeFile));
private static string GetServerCacheTimeFile(string appIdServer, string branchName) => IOUtils.NormalizePath(Path.Combine(GetServerCacheFolder(appIdServer, branchName), Config.Default.LastUpdatedTimeFile));
private static string GetServerCacheVersionFile(string branchName) => IOUtils.NormalizePath(Path.Combine(GetServerCacheFolder(branchName), Config.Default.ServerBinaryRelativePath, Config.Default.ServerExeFile));
private static string GetServerCacheVersionFile(string appIdServer, string branchName) => IOUtils.NormalizePath(Path.Combine(GetServerCacheFolder(appIdServer, branchName), Config.Default.ServerBinaryRelativePath, Config.Default.ServerExeFile));
private string GetServerExecutableFile() => IOUtils.NormalizePath(Path.Combine(_profile.InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ServerExeFile));
@ -2516,7 +2578,7 @@ namespace ServerManagerTool.Lib
Debug.WriteLine($"[INFO] {message}");
}
private void LogBranchError(string branchName, string error, bool includeProgressCallback = true)
private void LogBranchError(string appIdServer, string branchName, string error, bool includeProgressCallback = true)
{
if (string.IsNullOrWhiteSpace(error))
return;
@ -2526,10 +2588,12 @@ namespace ServerManagerTool.Lib
if (includeProgressCallback)
ProgressCallback?.Invoke(0, $"[ERROR] {error}");
Debug.WriteLine($"[ERROR] (Branch {GetBranchName(branchName) ?? "unknown"}) {error}");
var branchInfo = GetBranchInfo(appIdServer, branchName) ?? "unknown";
Debug.WriteLine($"[ERROR] (Branch {branchInfo}) {error}");
}
private void LogBranchMessage(string branchName, string message, bool includeProgressCallback = true)
private void LogBranchMessage(string appIdServer, string branchName, string message, bool includeProgressCallback = true)
{
message = message ?? string.Empty;
@ -2538,7 +2602,9 @@ namespace ServerManagerTool.Lib
if (includeProgressCallback)
ProgressCallback?.Invoke(0, $"{message}");
Debug.WriteLine($"[INFO] (Branch {GetBranchName(branchName) ?? "unknown"}) {message}");
var branchInfo = GetBranchInfo(appIdServer, branchName) ?? "unknown";
Debug.WriteLine($"[INFO] (Branch {branchInfo}) {message}");
}
private void LogProfileDebug(string message, bool includeProgressCallback = true)
@ -2957,16 +3023,17 @@ namespace ServerManagerTool.Lib
Mutex mutex = null;
var createdNew = false;
var branchInfo = GetBranchInfo(branch.AppIdServer, branch.BranchName) ?? "unknown";
if (OutputLogs)
{
_loggerBranch = GetLogger(GetLogFolder(LOGPREFIX_AUTOUPDATE), $"{LOGPREFIX_AUTOUPDATE}", $"BranchUpdate_{GetBranchName(branch.BranchName)}");
_loggerBranch = GetLogger(GetLogFolder(LOGPREFIX_AUTOUPDATE), $"{LOGPREFIX_AUTOUPDATE}", $"BranchUpdate_{branchInfo}");
_loggerProfile = GetLogger(GetProfileLogFolder(profile.ProfileId, LOGPREFIX_AUTOUPDATE), $"{LOGPREFIX_AUTOUPDATE}_{profile.ProfileId}", "Update");
}
try
{
LogBranchMessage(branch.BranchName, $"[{_profile.ProfileName}] Started server update process.");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"[{_profile.ProfileName}] Started server update process.");
// try to establish a mutex for the profile.
var mutexName = GetMutexName(_profile.InstallDirectory);
@ -2987,7 +3054,7 @@ namespace ServerManagerTool.Lib
UpdateFiles();
LogBranchMessage(branch.BranchName, $"[{_profile.ProfileName}] Finished server update process.");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"[{_profile.ProfileName}] Finished server update process.");
if (ExitCode != EXITCODE_NORMALEXIT)
{
@ -3000,7 +3067,7 @@ namespace ServerManagerTool.Lib
{
ExitCode = EXITCODE_PROCESSALREADYRUNNING;
LogProfileMessage("Cancelled server update process, could not lock server.");
LogBranchMessage(branch.BranchName, $"[{_profile.ProfileName}] Cancelled server update process, could not lock server.");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"[{_profile.ProfileName}] Cancelled server update process, could not lock server.");
}
}
catch (Exception ex)
@ -3047,47 +3114,50 @@ namespace ServerManagerTool.Lib
Mutex mutex = null;
var createdNew = false;
var branchInfo = GetBranchInfo(branch.AppIdServer, branch.BranchName) ?? "unknown";
if (OutputLogs)
_loggerBranch = GetLogger(GetLogFolder(LOGPREFIX_AUTOUPDATE), $"{LOGPREFIX_AUTOUPDATE}", $"BranchUpdate_{GetBranchName(branch.BranchName)}");
{
_loggerBranch = GetLogger(GetLogFolder(LOGPREFIX_AUTOUPDATE), $"{LOGPREFIX_AUTOUPDATE}", $"BranchUpdate_{branchInfo}");
}
try
{
LogMessage($"[{GetBranchName(branch.BranchName)}] Started branch update process.");
LogMessage($"[{branchInfo}] Started branch update process.");
var cacheFolder = GetServerCacheFolder(branch.BranchName);
var cacheFolder = GetServerCacheFolder(branch.AppIdServer, branch.BranchName);
// try to establish a mutex for the profile.
var mutexName = GetMutexName(cacheFolder);
LogBranchMessage(branch.BranchName, $"Attempting to establish a lock on the cache ({mutexName})");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"Attempting to establish a lock on the cache ({mutexName})");
mutex = new Mutex(true, mutexName, out createdNew);
if (!createdNew)
{
var timeout = new TimeSpan(0, MUTEX_TIMEOUT, 0);
LogBranchMessage(branch.BranchName, $"Could not lock cache, waiting for cache to unlock - timeout set to {timeout}.");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"Could not lock cache, waiting for cache to unlock - timeout set to {timeout}.");
createdNew = mutex.WaitOne(timeout);
}
// check if the mutex was established
if (createdNew)
{
LogBranchMessage(branch.BranchName, "Cache lock established.\r\n");
LogBranchMessage(branch.AppIdServer, branch.BranchName, "Cache lock established.\r\n");
// update the server cache for the branch
UpdateServerCache(branch.BranchName, branch.BranchPassword);
UpdateServerCache(branch.AppIdServer, branch.BranchName, branch.BranchPassword);
if (ExitCode != EXITCODE_NORMALEXIT)
{
if (Config.Default.EmailNotify_AutoUpdate)
SendEmail($"{GetBranchName(branch.BranchName)} branch update", Config.Default.Alert_UpdateProcessError, true);
SendEmail($"{branchInfo} branch update", Config.Default.Alert_UpdateProcessError, true);
ProcessAlert(AlertType.Error, Config.Default.Alert_UpdateProcessError);
}
if (ExitCode == EXITCODE_NORMALEXIT)
{
// get the profile associated with the branch
var profiles = _profiles.Keys.Where(p => p.EnableAutoUpdate && string.Equals(p.BranchName, branch.BranchName, StringComparison.OrdinalIgnoreCase));
var profiles = _profiles.Keys.Where(p => p.EnableAutoUpdate && string.Equals(p.AppIdServer, branch.AppIdServer, StringComparison.OrdinalIgnoreCase) && string.Equals(p.BranchName, branch.BranchName, StringComparison.OrdinalIgnoreCase));
var profileExitCodes = new ConcurrentDictionary<ServerProfileSnapshot, int>();
if (Config.Default.AutoUpdate_ParallelUpdate)
@ -3132,27 +3202,27 @@ namespace ServerManagerTool.Lib
ExitCode = EXITCODE_EXITWITHERRORS;
}
LogMessage($"[{GetBranchName(branch.BranchName)}] Finished branch update process.");
LogMessage($"[{branchInfo}] Finished branch update process.");
}
else
{
ExitCode = EXITCODE_PROCESSALREADYRUNNING;
LogMessage($"[{GetBranchName(branch.BranchName)}] Cancelled branch update process, could not lock cache.");
LogMessage($"[{branchInfo}] Cancelled branch update process, could not lock cache.");
}
}
catch (Exception ex)
{
LogBranchError(branch.BranchName, ex.Message);
LogBranchError(branch.BranchName, ex.GetType().ToString());
LogBranchError(branch.AppIdServer, branch.BranchName, ex.Message);
LogBranchError(branch.AppIdServer, branch.BranchName, ex.GetType().ToString());
if (ex.InnerException != null)
{
LogBranchMessage(branch.BranchName, $"InnerException - {ex.InnerException.Message}");
LogBranchMessage(branch.BranchName, ex.InnerException.GetType().ToString());
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"InnerException - {ex.InnerException.Message}");
LogBranchMessage(branch.AppIdServer, branch.BranchName, ex.InnerException.GetType().ToString());
}
LogBranchMessage(branch.BranchName, $"StackTrace\r\n{ex.StackTrace}");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"StackTrace\r\n{ex.StackTrace}");
if (Config.Default.EmailNotify_AutoUpdate)
SendEmail($"{GetBranchName(branch.BranchName)} branch update", Config.Default.Alert_UpdateProcessError, true);
SendEmail($"{branchInfo} branch update", Config.Default.Alert_UpdateProcessError, true);
ProcessAlert(AlertType.Error, Config.Default.Alert_UpdateProcessError);
ExitCode = EXITCODE_UNKNOWNTHREADERROR;
}
@ -3169,8 +3239,8 @@ namespace ServerManagerTool.Lib
}
}
LogBranchMessage(branch.BranchName, "");
LogBranchMessage(branch.BranchName, $"Exitcode = {ExitCode}");
LogBranchMessage(branch.AppIdServer, branch.BranchName, "");
LogBranchMessage(branch.AppIdServer, branch.BranchName, $"Exitcode = {ExitCode}");
return ExitCode;
}

View file

@ -650,6 +650,14 @@ namespace ServerManagerTool.Lib
#endregion
#region Server Details
public static readonly DependencyProperty UseTestliveProperty = DependencyProperty.Register(nameof(UseTestlive), typeof(bool), typeof(ServerProfile), new PropertyMetadata(false));
[DataMember]
public bool UseTestlive
{
get { return (bool)GetValue(UseTestliveProperty); }
set { SetValue(UseTestliveProperty, value); }
}
public static readonly DependencyProperty BranchNameProperty = DependencyProperty.Register(nameof(BranchName), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
[DataMember]
public string BranchName
@ -786,7 +794,8 @@ namespace ServerManagerTool.Lib
try
{
var manifestFile = ModUtils.GetSteamManifestFile(InstallDirectory);
var appIdServer = UseTestlive ? Config.Default.AppIdServer_Testlive : Config.Default.AppIdServer;
var manifestFile = ModUtils.GetSteamManifestFile(InstallDirectory, appIdServer);
if (string.IsNullOrWhiteSpace(manifestFile) || !File.Exists(manifestFile))
return;
@ -1256,7 +1265,7 @@ namespace ServerManagerTool.Lib
validationMessage = string.Empty;
StringBuilder result = new StringBuilder();
var appId = Config.Default.AppId;
var appId = UseTestlive ? Config.Default.AppId_Testlive : Config.Default.AppId;
// checking the port values are within the valid range
if (ServerPort < ushort.MinValue || ServerPort > ushort.MaxValue)
@ -1593,6 +1602,7 @@ namespace ServerManagerTool.Lib
public void ResetServerDetailsSection()
{
this.ClearValue(UseTestliveProperty);
this.ClearValue(BranchNameProperty);
this.ClearValue(BranchPasswordProperty);
}
@ -1680,6 +1690,7 @@ namespace ServerManagerTool.Lib
private void SyncServerDetails(ServerProfile sourceProfile)
{
this.SetValue(UseTestliveProperty, sourceProfile.UseTestlive);
this.SetValue(BranchNameProperty, sourceProfile.BranchName);
this.SetValue(BranchPasswordProperty, sourceProfile.BranchPassword);
}

View file

@ -32,6 +32,9 @@ namespace ServerManagerTool.Lib
public bool MOTDIntervalEnabled;
public int MOTDInterval;
public string AppId;
public string AppIdServer;
public bool UseTestlive;
public string BranchName;
public string BranchPassword;
@ -75,6 +78,9 @@ namespace ServerManagerTool.Lib
MOTDIntervalEnabled = profile.MOTDIntervalEnabled && !string.IsNullOrWhiteSpace(profile.MOTD),
MOTDInterval = Math.Max(1, Math.Min(int.MaxValue, profile.MOTDInterval)),
AppId = profile.UseTestlive ? Config.Default.AppId_Testlive : Config.Default.AppId,
AppIdServer = profile.UseTestlive ? Config.Default.AppIdServer_Testlive : Config.Default.AppIdServer,
UseTestlive = profile.UseTestlive,
BranchName = profile.BranchName,
BranchPassword = profile.BranchPassword,

View file

@ -659,8 +659,10 @@ namespace ServerManagerTool.Lib
// Server Update Section
// *********************
var branchInfo = ServerApp.GetBranchInfo(branch?.AppIdServer, branch?.BranchName);
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} Starting server update.");
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} Server branch: {ServerApp.GetBranchName(branch?.BranchName)}.");
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} Server branch: {branchInfo}.");
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} Profile name: {this.ProfileSnapshot.ProfileName}.");
// create the branch arguments
@ -678,8 +680,7 @@ namespace ServerManagerTool.Lib
// Check if this is a new server installation.
if (isNewInstallation && Config.Default.AutoUpdate_EnableUpdate && !string.IsNullOrWhiteSpace(Config.Default.AutoUpdate_CacheDir))
{
var branchName = string.IsNullOrWhiteSpace(branch?.BranchName) ? Config.Default.DefaultServerBranchName : branch.BranchName;
var cacheFolder = IOUtils.NormalizePath(Path.Combine(Config.Default.AutoUpdate_CacheDir, $"{Config.Default.ServerBranchFolderPrefix}{branchName}"));
var cacheFolder = ServerApp.GetServerCacheFolder(branch?.AppIdServer, branch?.BranchName);
// check if the auto-update facility is enabled and the cache folder defined.
if (!string.IsNullOrWhiteSpace(cacheFolder) && Directory.Exists(cacheFolder))
@ -718,7 +719,7 @@ namespace ServerManagerTool.Lib
};
var steamCmdRemoveQuit = CommonConfig.Default.SteamCmdRemoveQuit && !Config.Default.SteamCmdRedirectOutput;
var steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, this.ProfileSnapshot.InstallDirectory, Config.Default.AppIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
var steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallServerArgsFormat, Config.Default.SteamCmd_AnonymousUsername, this.ProfileSnapshot.InstallDirectory, this.ProfileSnapshot.AppIdServer, steamCmdInstallServerBetaArgs.ToString(), validate ? "validate" : string.Empty);
var workingDirectory = Config.Default.DataPath;
success = await ServerUpdater.UpgradeServerAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, this.ProfileSnapshot.InstallDirectory, Config.Default.SteamCmdRedirectOutput ? serverOutputHandler : null, cancellationToken, steamCmdRemoveQuit ? ProcessWindowStyle.Normal : ProcessWindowStyle.Minimized);
@ -811,16 +812,27 @@ namespace ServerManagerTool.Lib
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} Mod {modTitle}.");
var modCachePath = ModUtils.GetModCachePath(modId);
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId);
var modPath = ModUtils.GetModPath(this.ProfileSnapshot.InstallDirectory, modId);
var modTimeFile = ModUtils.GetLatestModTimeFile(this.ProfileSnapshot.InstallDirectory, modId);
var modCacheLastUpdated = 0;
var downloadMod = true;
var copyMod = true;
var updateError = false;
if (modDetail?.creator_app_id != null && !modDetail.creator_app_id.Equals(this.ProfileSnapshot.AppId, StringComparison.OrdinalIgnoreCase))
{
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} ***************************************************************************");
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} ERROR: Mod cannot be updated, this mod does not belong to this application.");
progressCallback?.Invoke(0, $"{SteamCmdUpdater.OUTPUT_PREFIX} ***************************************************************************");
downloadMod = false;
copyMod = false;
updateError = true;
}
var modCachePath = ModUtils.GetModCachePath(modId, this.ProfileSnapshot.AppId);
var cacheTimeFile = ModUtils.GetLatestModCacheTimeFile(modId, this.ProfileSnapshot.AppId);
var modPath = ModUtils.GetModPath(this.ProfileSnapshot.InstallDirectory, modId);
var modTimeFile = ModUtils.GetLatestModTimeFile(this.ProfileSnapshot.InstallDirectory, modId);
if (downloadMod)
{
// check if the mod needs to be downloaded, or force the download.
@ -893,9 +905,9 @@ namespace ServerManagerTool.Lib
var steamCmdArgs = string.Empty;
var steamCmdRemoveQuit = CommonConfig.Default.SteamCmdRemoveQuit && !Config.Default.SteamCmdRedirectOutput;
if (Config.Default.SteamCmd_UseAnonymousCredentials)
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_AnonymousUsername, Config.Default.AppId, modId);
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_AnonymousUsername, this.ProfileSnapshot.AppId, modId);
else
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_Username, Config.Default.AppId, modId);
steamCmdArgs = SteamUtils.BuildSteamCmdArguments(steamCmdRemoveQuit, Config.Default.SteamCmdInstallModArgsFormat, Config.Default.SteamCmd_Username, this.ProfileSnapshot.AppId, modId);
var workingDirectory = Config.Default.DataPath;
modSuccess = await ServerUpdater.UpgradeModsAsync(steamCmdFile, steamCmdArgs, workingDirectory, null, null, Config.Default.SteamCmdRedirectOutput ? modOutputHandler : null, cancellationToken, steamCmdRemoveQuit ? ProcessWindowStyle.Normal : ProcessWindowStyle.Minimized);
@ -915,7 +927,7 @@ namespace ServerManagerTool.Lib
if (modDetail == null || modDetail.time_updated <= 0)
{
// get the version number from the steamcmd workshop file.
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(), modId).ToString();
steamLastUpdated = ModUtils.GetSteamWorkshopLatestTime(ModUtils.GetSteamWorkshopFile(this.ProfileSnapshot.AppId), modId).ToString();
}
// update the last updated file with the steam updated time.

View file

@ -21,7 +21,7 @@
<ResourceDictionary Source="..\Styles\Default.xaml"/>
</ResourceDictionary.MergedDictionaries>
<ControlTemplate x:Key="ExpanderTemplateSE" TargetType="{x:Type Expander}">
<ControlTemplate x:Key="ExpanderTemplate" TargetType="{x:Type Expander}">
<Border BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" SnapsToDevicePixels="true" Padding="1" Margin="0,0,0,3" BorderBrush="Black">
<DockPanel Background="#FFEAE7E0">
<ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FocusVisualStyle="{StaticResource ExpanderHeaderFocusVisual}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="4,4,1,4" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}" Style="{StaticResource ExpanderDownHeaderStyle}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
@ -55,6 +55,40 @@
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="ExpanderTemplateTestlive" TargetType="{x:Type Expander}">
<Border BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" SnapsToDevicePixels="true" Padding="1" Margin="0,0,0,3" BorderBrush="Black">
<DockPanel Background="#FFEAE0E0">
<ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FocusVisualStyle="{StaticResource ExpanderHeaderFocusVisual}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="4,4,1,4" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}" Style="{StaticResource ExpanderDownHeaderStyle}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
<ContentPresenter x:Name="ExpandSite" DockPanel.Dock="Bottom" Focusable="false" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="10,0,0,0"/>
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="true">
<Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
</Trigger>
<Trigger Property="IsExpanded" Value="false">
<Setter Property="Visibility" TargetName="ExpandSite" Value="Collapsed"/>
</Trigger>
<Trigger Property="ExpandDirection" Value="Right">
<Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Right"/>
<Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Left"/>
<Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderRightHeaderStyle}"/>
</Trigger>
<Trigger Property="ExpandDirection" Value="Up">
<Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Top"/>
<Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Bottom"/>
<Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderUpHeaderStyle}"/>
</Trigger>
<Trigger Property="ExpandDirection" Value="Left">
<Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Left"/>
<Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Right"/>
<Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderLeftHeaderStyle}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ResourceDictionary>
</UserControl.Resources>
@ -410,7 +444,12 @@
<Expander.Style>
<Style BasedOn="{StaticResource ExpanderStyle1}" TargetType="{x:Type Expander}">
<Setter Property="Template" Value="{StaticResource ExpanderTemplateSE}"/>
<Setter Property="Template" Value="{StaticResource ExpanderTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding UseTestlive}" Value="True">
<Setter Property="Template" Value="{StaticResource ExpanderTemplateTestlive}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
@ -903,7 +942,12 @@
<Expander.Style>
<Style BasedOn="{StaticResource ExpanderStyle1}" TargetType="{x:Type Expander}">
<Setter Property="Template" Value="{StaticResource ExpanderTemplateSE}"/>
<Setter Property="Template" Value="{StaticResource ExpanderTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding UseTestlive}" Value="True">
<Setter Property="Template" Value="{StaticResource ExpanderTemplateTestlive}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
@ -1070,7 +1114,12 @@
<Expander.Style>
<Style BasedOn="{StaticResource ExpanderStyle1}" TargetType="{x:Type Expander}">
<Setter Property="Template" Value="{StaticResource ExpanderTemplateSE}"/>
<Setter Property="Template" Value="{StaticResource ExpanderTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding UseTestlive}" Value="True">
<Setter Property="Template" Value="{StaticResource ExpanderTemplateTestlive}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
@ -1135,7 +1184,12 @@
<Expander.Style>
<Style BasedOn="{StaticResource ExpanderStyle1}" TargetType="{x:Type Expander}">
<Setter Property="Template" Value="{StaticResource ExpanderTemplateSE}"/>
<Setter Property="Template" Value="{StaticResource ExpanderTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding UseTestlive}" Value="True">
<Setter Property="Template" Value="{StaticResource ExpanderTemplateTestlive}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
@ -1154,7 +1208,40 @@
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<GroupBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="6" Header="{DynamicResource ServerSettings_BranchLabel}" DataContext="{Binding Runtime, ElementName=SettingsControl}">
<CheckBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="5" IsChecked="{Binding UseTestlive, Mode=TwoWay}" Content="{DynamicResource ServerSettings_UseTestliveLabel}" HorizontalAlignment="Left" ToolTip="{DynamicResource ServerSettings_UseTestliveTooltip}">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Runtime.Status, ElementName=SettingsControl}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Runtime.Status, ElementName=SettingsControl}" Value="{x:Static ce:ServerStatus.Initializing}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Runtime.Status, ElementName=SettingsControl}" Value="{x:Static ce:ServerStatus.Running}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Runtime.Status, ElementName=SettingsControl}" Value="{x:Static ce:ServerStatus.Stopping}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Runtime.Status, ElementName=SettingsControl}" Value="{x:Static ce:ServerStatus.Stopped}">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding Runtime.Status, ElementName=SettingsControl}" Value="{x:Static ce:ServerStatus.Unknown}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Runtime.Status, ElementName=SettingsControl}" Value="{x:Static ce:ServerStatus.Updating}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Runtime.Status, ElementName=SettingsControl}" Value="{x:Static ce:ServerStatus.Uninstalled}">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
<GroupBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="6" Header="{DynamicResource ServerSettings_BranchLabel}" DataContext="{Binding Runtime, ElementName=SettingsControl}">
<GroupBox.Style>
<Style BasedOn="{StaticResource GroupBoxStyle}" TargetType="{x:Type GroupBox}">
<Style.Triggers>
@ -1216,7 +1303,12 @@
<Expander.Style>
<Style BasedOn="{StaticResource ExpanderStyle1}" TargetType="{x:Type Expander}">
<Setter Property="Template" Value="{StaticResource ExpanderTemplateSE}"/>
<Setter Property="Template" Value="{StaticResource ExpanderTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding UseTestlive}" Value="True">
<Setter Property="Template" Value="{StaticResource ExpanderTemplateTestlive}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>

View file

@ -440,10 +440,11 @@ namespace ServerManagerTool
private void PatchNotes_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(Config.Default.AppPatchNotesUrl))
var url = this.Settings.UseTestlive ? Config.Default.AppPatchNotesUrl_Testlive : Config.Default.AppPatchNotesUrl;
if (string.IsNullOrWhiteSpace(url))
return;
Process.Start(Config.Default.AppPatchNotesUrl);
Process.Start(url);
}
private void NeedAdmin_Click(object sender, RoutedEventArgs e)
@ -588,7 +589,8 @@ namespace ServerManagerTool
}
// <data folder>\SteamCMD\steamapps\workshop\content\<app id>
folder = Path.Combine(Config.Default.DataPath, CommonConfig.Default.SteamCmdRelativePath, Config.Default.AppSteamWorkshopFolderRelativePath);
var workshopPath = string.Format(Config.Default.AppSteamWorkshopFolderRelativePath, this.Settings.UseTestlive ? Config.Default.AppId_Testlive : Config.Default.AppId);
folder = Path.Combine(Config.Default.DataPath, CommonConfig.Default.SteamCmdRelativePath, workshopPath);
if (Directory.Exists(folder))
{
foreach (var modFolder in Directory.GetDirectories(folder))

View file

@ -92,7 +92,7 @@ namespace ServerManagerTool.Utils
}
}
public static string GetLatestModCacheTimeFile(string modId) => IOUtils.NormalizePath(Path.Combine(GetModCachePath(modId), Config.Default.LastUpdatedTimeFile));
public static string GetLatestModCacheTimeFile(string modId, string appId) => IOUtils.NormalizePath(Path.Combine(GetModCachePath(modId, appId), Config.Default.LastUpdatedTimeFile));
public static string GetLatestModTimeFile(string installDirectory, string modId) => IOUtils.NormalizePath(Path.Combine(installDirectory, Config.Default.ServerModsRelativePath, $"{modId}.txt"));
@ -104,7 +104,11 @@ namespace ServerManagerTool.Utils
return serverMap.Trim();
}
public static string GetModCachePath(string modId) => IOUtils.NormalizePath(Path.Combine(Config.Default.DataPath, CommonConfig.Default.SteamCmdRelativePath, Config.Default.AppSteamWorkshopFolderRelativePath, modId));
public static string GetModCachePath(string modId, string appId)
{
var workshopPath = string.Format(Config.Default.AppSteamWorkshopFolderRelativePath, appId);
return IOUtils.NormalizePath(Path.Combine(Config.Default.DataPath, CommonConfig.Default.SteamCmdRelativePath, workshopPath, modId));
}
public static List<string> GetModIdList(string modIds)
{
@ -136,9 +140,17 @@ namespace ServerManagerTool.Utils
public static string GetModPath(string installDirectory, string modId) => GetModRootPath(installDirectory);
public static string GetSteamManifestFile(string installDirectory) => IOUtils.NormalizePath(Path.Combine(installDirectory, Config.Default.SteamManifestFolderRelativePath, Config.Default.AppSteamManifestFile));
public static string GetSteamManifestFile(string installDirectory, string appIdServer)
{
var fileName = string.Format(Config.Default.AppSteamManifestFile, appIdServer);
return IOUtils.NormalizePath(Path.Combine(installDirectory, Config.Default.SteamManifestFolderRelativePath, fileName));
}
public static string GetSteamWorkshopFile() => IOUtils.NormalizePath(Path.Combine(Config.Default.DataPath, CommonConfig.Default.SteamCmdRelativePath, Config.Default.SteamWorkshopFolderRelativePath, Config.Default.AppSteamWorkshopFile));
public static string GetSteamWorkshopFile(string appId)
{
var fileName = string.Format(Config.Default.AppSteamWorkshopFile, appId);
return IOUtils.NormalizePath(Path.Combine(Config.Default.DataPath, CommonConfig.Default.SteamCmdRelativePath, Config.Default.SteamWorkshopFolderRelativePath, fileName));
}
public static int GetSteamWorkshopLatestTime(string workshopFile, string modId)
{

View file

@ -7,6 +7,30 @@
<link href="https://servermanagers.freeforums.net/" />
<updated>2022-07-15T00:00:00Z</updated>
<entry>
<id>urn:uuid:6D1F49A0-06E6-415F-AA92-AACD598BC50C</id>
<title>1.1.80 (1.1.80.1)</title>
<summary>1.1.80.1</summary>
<link href="" />
<updated>2022-08-07T00:00:00Z</updated>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, Verdana, Helvetica, Sans-Serif;font-size: .8em;">
<p>
<u style="font-size: .9em;">CHANGE</u>
<br/>
<ul>
<li>Server Details Section - added new option to use the Conan Testlive Dedicated Server files. This new option will switch the steam application id of the server files to use the Conan Testlive Dedicated Server files, instead of the Conan Dedicated Server files.</li>
<li>Server Update - updated the code to determine which set of dedicated server files (Conan or Conan Testlive) is required when performing server and mod file updates. Separate Cache folders will be maintained for each.</li>
</ul>
</p>
</div>
</content>
<author>
<name>bletch</name>
<email>bletch1971@hotmail.com</email>
</author>
</entry>
<entry>
<id>urn:uuid:8CDA70CF-E8B8-4B9B-AD50-AD9A8B528E5B</id>
<title>1.1.79 (1.1.79.3)</title>

View file

@ -5,67 +5,22 @@
<title>Conan Server Manager Version Feed</title>
<subtitle>This is the Conan Server Manager beta version feed.</subtitle>
<link href="https://servermanagers.freeforums.net/" />
<updated>2022-07-25T00:00:00Z</updated>
<updated>2022-08-07T00:00:00Z</updated>
<entry>
<id>urn:uuid:8CDA70CF-E8B8-4B9B-AD50-AD9A8B528E5B</id>
<title>1.1.79 (1.1.79.3)</title>
<summary>1.1.79.3</summary>
<id>urn:uuid:6D1F49A0-06E6-415F-AA92-AACD598BC50C</id>
<title>1.1.80 (1.1.80.1)</title>
<summary>1.1.80.1</summary>
<link href="" />
<updated>2022-07-25T00:00:00Z</updated>
<updated>2022-08-07T00:00:00Z</updated>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, Verdana, Helvetica, Sans-Serif;font-size: .8em;">
<p>
<u style="font-size: .9em;">BUGFIX</u>
<u style="font-size: .9em;">CHANGE</u>
<br/>
<ul>
<li>Fixed a crash bug when trying to set the logging folder.</li>
</ul>
</p>
</div>
</content>
<author>
<name>bletch</name>
<email>bletch1971@hotmail.com</email>
</author>
</entry>
<entry>
<id>urn:uuid:8CDA70CF-E8B8-4B9B-AD50-AD9A8B528E5B</id>
<title>1.1.79 (1.1.79.2)</title>
<summary>1.1.79.2</summary>
<link href="" />
<updated>2022-07-16T00:00:00Z</updated>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, Verdana, Helvetica, Sans-Serif;font-size: .8em;">
<p>
<u style="font-size: .9em;">BUGFIX</u>
<br/>
<ul>
<li>Added a check for a valid configuration file when starting the server manager.\r\nIf config file is not valid, then it will delete the config file and shutdown the manager, with a message to restart the manager.</li>
</ul>
</p>
</div>
</content>
<author>
<name>bletch</name>
<email>bletch1971@hotmail.com</email>
</author>
</entry>
<entry>
<id>urn:uuid:8CDA70CF-E8B8-4B9B-AD50-AD9A8B528E5B</id>
<title>1.1.79 (1.1.79.1)</title>
<summary>1.1.79.1</summary>
<link href="" />
<updated>2022-07-15T00:00:00Z</updated>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: Arial, Verdana, Helvetica, Sans-Serif;font-size: .8em;">
<p>
<u style="font-size: .9em;">BUGFIX</u>
<br/>
<ul>
<li>Server Status - changed the server status code to stop the status cycling and to be more accurate.</li>
<li>Server Details Section - added new option to use the Conan Testlive Dedicated Server files. This new option will switch the steam application id of the server files to use the Conan Testlive Dedicated Server files, instead of the Conan Dedicated Server files.</li>
<li>Server Update - updated the code to determine which set of dedicated server files (Conan or Conan Testlive) is required when performing server and mod file updates. Separate Cache folders will be maintained for each.</li>
</ul>
</p>
</div>

View file

@ -479,8 +479,11 @@ namespace ServerManagerTool
{
WorkshopFileDetailResponse localCache = null;
var appId = _profile.UseTestlive ? Config.Default.AppId_Testlive : Config.Default.AppId;
var workshopCacheFile = string.Format(Config.Default.WorkshopCacheFile, appId);
await Task.Run(() => {
var file = Path.Combine(Config.Default.DataPath, Config.Default.WorkshopCacheFile);
var file = Path.Combine(Config.Default.DataPath, workshopCacheFile);
// try to load the cache file.
localCache = WorkshopFileDetailResponse.Load(file);

View file

@ -160,8 +160,11 @@ namespace ServerManagerTool
WorkshopFileDetailResponse localCache = null;
WorkshopFileDetailResponse steamCache = null;
var appId = _profile.UseTestlive ? Config.Default.AppId_Testlive : Config.Default.AppId;
var workshopCacheFile = string.Format(Config.Default.WorkshopCacheFile, appId);
await Task.Run( () => {
var file = Path.Combine(Config.Default.DataPath, Config.Default.WorkshopCacheFile);
var file = Path.Combine(Config.Default.DataPath, workshopCacheFile);
// try to load the cache file.
localCache = WorkshopFileDetailResponse.Load(file);
@ -174,7 +177,7 @@ namespace ServerManagerTool
// check if the cache exists
if (steamCache == null)
{
steamCache = SteamUtils.GetSteamModDetails(Config.Default.AppId);
steamCache = SteamUtils.GetSteamModDetails(appId);
if (steamCache != null)
steamCache.Save(file);
else

View file

@ -74,6 +74,14 @@ namespace ServerManagerTool.Common.Utils
}
public static PublishedFileDetailsResponse GetSteamModDetails(List<string> modIdList)
{
return GetSteamModDetails(new List<(string AppId, List<string> ModIdList)>()
{
("", modIdList),
});
}
public static PublishedFileDetailsResponse GetSteamModDetails(List<(string AppId, List<string> ModIdList)> appMods)
{
const int MAX_IDS = 20;
@ -83,57 +91,63 @@ namespace ServerManagerTool.Common.Utils
try
{
if (modIdList == null || modIdList.Count == 0)
if (appMods == null || appMods.Count == 0)
return new PublishedFileDetailsResponse();
int remainder;
var totalRequests = Math.DivRem(modIdList.Count, MAX_IDS, out remainder);
if (remainder > 0)
totalRequests++;
var requestIndex = 0;
while (requestIndex < totalRequests)
foreach (var appMod in appMods)
{
var count = 0;
var postData = "";
for (var index = requestIndex * MAX_IDS; count < MAX_IDS && index < modIdList.Count; index++)
if (appMod.ModIdList.Count == 0)
continue;
int remainder;
var totalRequests = Math.DivRem(appMod.ModIdList.Count, MAX_IDS, out remainder);
if (remainder > 0)
totalRequests++;
var requestIndex = 0;
while (requestIndex < totalRequests)
{
postData += $"&publishedfileids[{count}]={modIdList[index]}";
count++;
}
postData = $"key={SteamWebApiKey}&format=json&itemcount={count}{postData}";
var data = Encoding.ASCII.GetBytes(postData);
var httpRequest = WebRequest.Create("https://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v1/");
httpRequest.Timeout = 30000;
httpRequest.Method = "POST";
httpRequest.ContentType = "application/x-www-form-urlencoded";
httpRequest.ContentLength = data.Length;
using (var stream = httpRequest.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
var responseString = new StreamReader(httpResponse.GetResponseStream()).ReadToEnd();
var result = JsonUtils.Deserialize<PublishedFileDetailsResult>(responseString);
if (result != null && result.response != null)
{
if (response == null)
response = result.response;
else
var count = 0;
var postData = "";
for (var index = requestIndex * MAX_IDS; count < MAX_IDS && index < appMod.ModIdList.Count; index++)
{
response.resultcount += result.response.resultcount;
response.publishedfiledetails.AddRange(result.response.publishedfiledetails);
postData += $"&publishedfileids[{count}]={appMod.ModIdList[index]}";
count++;
}
}
requestIndex++;
};
postData = $"key={SteamWebApiKey}&format=json&itemcount={count}{postData}";
var data = Encoding.ASCII.GetBytes(postData);
var httpRequest = WebRequest.Create("https://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v1/");
httpRequest.Timeout = 30000;
httpRequest.Method = "POST";
httpRequest.ContentType = "application/x-www-form-urlencoded";
httpRequest.ContentLength = data.Length;
using (var stream = httpRequest.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
var responseString = new StreamReader(httpResponse.GetResponseStream()).ReadToEnd();
var result = JsonUtils.Deserialize<PublishedFileDetailsResult>(responseString);
if (result != null && result.response != null)
{
if (response == null)
response = result.response;
else
{
response.resultcount += result.response.resultcount;
response.publishedfiledetails.AddRange(result.response.publishedfiledetails);
}
}
requestIndex++;
};
}
return response ?? new PublishedFileDetailsResponse();
}