internal void UpdateMod(ModEntry m, Settings settings) { // Check if mod directory exists if (!Directory.Exists(m.Path)) { Log.Warn($"Hiding mod {m.ID} because the directory {m.Path} no longer exists."); m.AddState(ModState.NotInstalled); m.AddState(ModState.NotLoaded); m.isHidden = true; return; } // Check if in ModPaths if (!settings.ModPaths.Any(modPath => m.IsInModPath(modPath))) { Log.Warn($"The mod {m.ID} is not located in any of the configured mod directories -> ModState.NotLoaded"); m.AddState(ModState.NotLoaded); } // Update Source if (m.Source == ModSource.Unknown) { if (m.Path.IndexOf(@"\SteamApps\workshop\", StringComparison.OrdinalIgnoreCase) != -1) { m.SetSource(ModSource.SteamWorkshop); } else { // in workshop path but not loaded via steam m.SetSource(ModSource.Manual); } Log.Info("Updated unknown mod source to " + m.Source); } // Ensure source ID exists if (m.WorkshopID <= 0) { if (m.Source == ModSource.SteamWorkshop && long.TryParse(Path.GetFileName(m.Path), out var sourceID)) { m.WorkshopID = sourceID; } else { m.WorkshopID = new ModInfo(m.GetModInfoFile()).PublishedFileID; } if (m.WorkshopID > 0) { Log.Info("Updated uninitialized WorkShop Id to " + m.WorkshopID); } } // Fill Date Added if (!m.DateAdded.HasValue) { m.DateAdded = DateTime.Now; } SteamUGCDetails_t workshopDetails = new SteamUGCDetails_t(); // Check Workshop for infos if (m.WorkshopID != 0) { workshopDetails = Workshop.GetDetails((ulong)m.WorkshopID, string.IsNullOrEmpty(m.Description)); } if (workshopDetails.m_eResult == EResult.k_EResultOK) { Log.Debug("Processing Workshop details for " + m.ID); if (!m.ManualName) { m.Name = workshopDetails.m_rgchTitle; } m.DateCreated = DateTimeOffset.FromUnixTimeSeconds(workshopDetails.m_rtimeCreated).DateTime; m.DateUpdated = DateTimeOffset.FromUnixTimeSeconds(workshopDetails.m_rtimeUpdated).DateTime; if (workshopDetails.m_rtimeAddedToUserList > 0) { m.DateAdded = DateTimeOffset.FromUnixTimeSeconds(workshopDetails.m_rtimeAddedToUserList).DateTime; } //m.Author = SteamWorkshop.GetUsername(value.m_ulSteamIDOwner); //MessageBox.Show(m.Author); // Update directory size m.RealizeSize(workshopDetails.m_nFileSize); if (m.Size < 0) { m.RealizeSize(Directory.EnumerateFiles(m.Path, "*", SearchOption.AllDirectories).Sum(fileName => new FileInfo(fileName).Length)); } if (string.IsNullOrEmpty(m.Description)) { m.Description = workshopDetails.m_rgchDescription; } if (workshopDetails.m_ulSteamIDOwner > 0) { string newAuthorName = Workshop.GetUsername(workshopDetails.m_ulSteamIDOwner); // Getusername() sometimes returns null, an empty string or "[unknown]". // We do not want to overwrite a potentially already correct author name in that case. if (!string.IsNullOrEmpty(newAuthorName) && newAuthorName != "[unknown]") { m.Author = newAuthorName; } } // Check Workshop for updates if (m.Source == ModSource.SteamWorkshop) { if (Workshop.GetDownloadStatus((ulong)m.WorkshopID).HasFlag(EItemState.k_EItemStateNeedsUpdate)) { Log.Info("Update available for " + m.ID); m.AddState(ModState.UpdateAvailable); } } // Check if it is built for WOTC try { // Parse .XComMod file var modInfo = new ModInfo(m.GetModInfoFile()); m.SetRequiresWOTC(modInfo.RequiresXPACK); } catch (InvalidOperationException ex) { Log.Error("Failed parsing XComMod file for " + m.ID, ex); SentrySdk.CaptureException(ex); Debug.Fail(ex.Message); } } else { Log.Debug("Processing local information for " + m.ID); m.DateCreated = Directory.GetCreationTime(m.Path); m.DateUpdated = Directory.GetLastWriteTime(m.Path); // Update directory size // slow, but necessary ? m.RealizeSize(Directory.EnumerateFiles(m.Path, "*", SearchOption.AllDirectories).Sum(fileName => new FileInfo(fileName).Length)); // Update Name and Description // look for .XComMod file try { // Parse .XComMod file var modInfo = new ModInfo(m.GetModInfoFile()); if (!m.ManualName || m.Name == "") { m.Name = modInfo.Title; } m.Description = modInfo.Description; m.SetRequiresWOTC(modInfo.RequiresXPACK); } catch (InvalidOperationException ex) { Log.Error("Failed parsing XComMod file for " + m.ID, ex); SentrySdk.CaptureException(ex); Debug.Fail(ex.Message); } } }
public string GetCategory(ModEntry mod) { return(Entries.First(entry => entry.Value.Entries.Contains(mod)).Key); }
internal void UpdateMod(ModEntry m, Settings settings) { // Check if in ModPaths if (!settings.ModPaths.Any(modPath => m.IsInModPath(modPath))) { m.State |= ModState.NotLoaded; } // Update Source if (m.Source == ModSource.Unknown) { if (m.Path.IndexOf(@"\SteamApps\workshop\", StringComparison.OrdinalIgnoreCase) != -1) { m.Source = ModSource.SteamWorkshop; } else { // in workshop path but not loaded via steam m.Source = ModSource.Manual; } } // Ensure source ID exists if (m.WorkshopID <= 0) { long sourceID; if (m.Source == ModSource.SteamWorkshop && long.TryParse(Path.GetFileName(m.Path), out sourceID)) { m.Source = ModSource.Manual; } else { sourceID = new ModInfo(m.GetModInfoFile()).PublishedFileID; } m.WorkshopID = sourceID; } // Fill Date Added if (!m.DateAdded.HasValue) { m.DateAdded = DateTime.Now; } // Check Workshop for infos if (m.WorkshopID != 0) { var publishedID = (ulong)m.WorkshopID; var value = Workshop.GetDetails(publishedID); if (!m.ManualName) { m.Name = value.m_rgchTitle; } m.DateCreated = DateTimeOffset.FromUnixTimeSeconds(value.m_rtimeCreated).DateTime; m.DateUpdated = DateTimeOffset.FromUnixTimeSeconds(value.m_rtimeUpdated).DateTime; if (value.m_rtimeAddedToUserList > 0) { m.DateAdded = DateTimeOffset.FromUnixTimeSeconds(value.m_rtimeAddedToUserList).DateTime; } //m.Author = SteamWorkshop.GetUsername(value.m_ulSteamIDOwner); //MessageBox.Show(m.Author); // Update directory size m.Size = value.m_nFileSize; if (m.Size < 0) { m.Size = Directory.EnumerateFiles(m.Path, "*", SearchOption.AllDirectories).Sum(fileName => new FileInfo(fileName).Length); } // Check Workshop for updates if (m.Source == ModSource.SteamWorkshop) { if ( Workshop.GetDownloadStatus((ulong)m.WorkshopID) .HasFlag(EItemState.k_EItemStateNeedsUpdate)) { m.State |= ModState.UpdateAvailable; } } } else { // Update directory size // slow, but necessary ? m.Size = Directory.EnumerateFiles(m.Path, "*", SearchOption.AllDirectories).Sum(fileName => new FileInfo(fileName).Length); } }
public ModEntry Import(string modDir, ModSource source = ModSource.Unknown) { // Check if Mod already loaded if (FindByPath(modDir) != null) { return(null); } // look for .XComMod file string infoFile = FindModInfo(modDir); if (infoFile == null) { return(null); } var modID = Path.GetFileNameWithoutExtension(infoFile); // Parse .XComMod file var modinfo = new ModInfo(infoFile); var mod = new ModEntry { Name = modinfo.Title ?? "Unnamed Mod", ID = modID, Path = modDir, isActive = false, DateAdded = DateTime.Now }; mod.AddState(ModState.New); mod.SetRequiresWOTC(modinfo.RequiresXPACK); mod.SetSource(source); if (source == ModSource.SteamWorkshop) { // for Workshop mods, the folder name represents the Workshop-Id var s = modDir.Split(Path.DirectorySeparatorChar).Last(); if (long.TryParse(s, out var workShopId)) { mod.WorkshopID = workShopId; } else { Log.Error($"Unable to parse WorkShop-Id ({s}) from Steam mod directory " + modDir); MessageBox.Show("A mod could not be loaded because the workshop ID failed to parse." + $"\nPlease check that the following directory conforms to valid workshop numbering.\n\nPath: {modDir}"); return(null); } } else if (source == ModSource.Manual) { // for mods from a custom mod path with custom folder names, we check if the XComMod file contains a Workshop-Id (i.e. publishedfileid) mod.WorkshopID = modinfo.PublishedFileID; } AddMod(modinfo.Category, mod); return(mod); }
public ModEntry Import(string modDir, ModSource source = ModSource.Unknown) { if (FindByPath(modDir) != null) { // Mod already loaded return(null); } // look for .XComMod file string infoFile; try { infoFile = Directory.GetFiles(modDir, "*.XComMod", SearchOption.TopDirectoryOnly).SingleOrDefault(); } catch (InvalidOperationException) { MessageBox.Show( $"A mod could not be loaded since it contains multiple .xcommod files\r\nPlease notify the mod creator.\r\n\r\nPath: {modDir}"); return(null); } if (infoFile == null) { return(null); } var modID = Path.GetFileNameWithoutExtension(infoFile); var isDupe = All.Any(m => m.ID == modID && string.Compare(m.Path, modDir, StringComparison.OrdinalIgnoreCase) == 0); // Parse .XComMod file var modinfo = new ModInfo(infoFile); var mod = new ModEntry { ID = modID, Name = modinfo.Title ?? "Unnamed Mod", Path = modDir, Source = source, isActive = false, DateAdded = DateTime.Now, State = ModState.New }; if (source == ModSource.SteamWorkshop) { var s = modDir.Split(Path.DirectorySeparatorChar).Last(); try { mod.WorkshopID = Convert.ToInt64(s); } catch (Exception) { MessageBox.Show( $"A mod could not be loaded because the workshop ID failed to parse.\r\nPlease check that the following directory conforms to valid workshop numbering.\r\n\r\nPath: {modDir}"); return(null); } } AddMod(modinfo.Category, mod); // mark dupes if (isDupe) { foreach (var m in All.Where(m => m.ID == modID)) { m.State |= ModState.DuplicateID; } } return(mod); }
public void RemoveMod(ModEntry mod) { var category = GetCategory(mod); this[category].Entries.Remove(mod); }
void UpdateSteamMod(ModEntry m, SteamUGCDetails_t workshopDetails) { if (m == null || m.WorkshopID <= 0) { return; } if (workshopDetails.m_eResult != EResult.k_EResultOK) { return; } Log.Debug("Processing Workshop details for " + m.ID); if (!m.ManualName) { m.Name = workshopDetails.m_rgchTitle; } m.DateCreated = DateTimeOffset.FromUnixTimeSeconds(workshopDetails.m_rtimeCreated).DateTime; m.DateUpdated = DateTimeOffset.FromUnixTimeSeconds(workshopDetails.m_rtimeUpdated).DateTime; if (workshopDetails.m_rtimeAddedToUserList > 0) { m.DateAdded = DateTimeOffset.FromUnixTimeSeconds(workshopDetails.m_rtimeAddedToUserList).DateTime; } // Update directory size m.RealizeSize(workshopDetails.m_nFileSize); if (m.Size < 0) { m.RealizeSize(Directory.EnumerateFiles(m.Path, "*", SearchOption.AllDirectories).Sum(fileName => new FileInfo(fileName).Length)); } if (string.IsNullOrEmpty(m.Description)) { m.Description = workshopDetails.m_rgchDescription; } // Request mod author name if necessary. if (string.IsNullOrEmpty(m.Author) || m.Author == ModEntry.DEFAULT_AUTHOR_NAME) { if (workshopDetails.m_ulSteamIDOwner > 0) { string newAuthorName = Workshop.GetUsername(workshopDetails.m_ulSteamIDOwner); // Getusername() sometimes returns null, an empty string or "[unknown]". // We do not want to overwrite a potentially already correct author name in that case. if (!string.IsNullOrEmpty(newAuthorName) && newAuthorName != "[unknown]") { m.Author = newAuthorName; } } } // We buffer the Steam tags so we do nor require another full UGC workshop request when the user chooses to use them. m.SteamTags = workshopDetails.m_rgchTags.Split(',').Select(s => s.TrimStart(' ').TrimEnd(' ')).Where(s => !string.IsNullOrWhiteSpace(s)).ToList(); // If the mod has dependencies, request the workshop id's of those mods. if (workshopDetails.m_unNumChildren > 0) { var dependencies = Workshop.GetDependencies(workshopDetails); if (dependencies != null) { m.Dependencies.Clear(); m.Dependencies.AddRange(dependencies.ConvertAll(val => (long)val)); } else { Log.Warn($"Dependency request for {m.WorkshopID} failed."); } } // Check Workshop for updates if (Workshop.GetDownloadStatus((ulong)m.WorkshopID).HasFlag(EItemState.k_EItemStateNeedsUpdate)) { Log.Info("Update available for " + m.ID); m.AddState(ModState.UpdateAvailable); } // Check if it is built for WOTC try { // Parse .XComMod file var modInfo = new ModInfo(m.GetModInfoFile()); m.SetRequiresWOTC(modInfo.RequiresXPACK); } catch (InvalidOperationException ex) { Log.Error("Failed parsing XComMod file for " + m.ID, ex); Debug.Fail(ex.Message); } }
bool VerifyModState(ModEntry m, Settings settings) { // Check if mod directory exists if (!Directory.Exists(m.Path)) { Log.Warn($"Hiding mod {m.ID} because the directory {m.Path} no longer exists."); m.AddState(ModState.NotInstalled); m.AddState(ModState.NotLoaded); m.isHidden = true; return(false); } // Check if in ModPaths if (!settings.ModPaths.Any(m.IsInModPath)) { Log.Warn($"The mod {m.ID} is not located in any of the configured mod directories -> ModState.NotLoaded"); m.AddState(ModState.NotLoaded); } // Update Source if (m.Source == ModSource.Unknown) { if (m.Path.IndexOf(@"\SteamApps\workshop\", StringComparison.OrdinalIgnoreCase) != -1) { m.SetSource(ModSource.SteamWorkshop); } else { // in workshop path but not loaded via steam m.SetSource(ModSource.Manual); } Log.Info("Updated unknown mod source to " + m.Source); } // Ensure source ID exists if (m.WorkshopID <= 0) { if (m.Source == ModSource.SteamWorkshop && long.TryParse(Path.GetFileName(m.Path), out var sourceID)) { m.WorkshopID = sourceID; } else { m.WorkshopID = new ModInfo(m.GetModInfoFile()).PublishedFileID; } if (m.WorkshopID > 0) { Log.Info("Updated uninitialized WorkShop Id to " + m.WorkshopID); } } // Fill Date Added if (!m.DateAdded.HasValue) { m.DateAdded = DateTime.Now; } return(true); }
public async void UpdateModAsync(ModEntry m, Settings settings) { await UpdateModsAsync(new List <ModEntry> { m }, settings); }
internal void UpdateMod(ModEntry m, Settings settings) { // Check if mod directory exists if (!Directory.Exists(m.Path)) { m.AddState(ModState.NotInstalled); m.AddState(ModState.NotLoaded); m.isHidden = true; return; } // Check if in ModPaths if (!settings.ModPaths.Any(modPath => m.IsInModPath(modPath))) { m.AddState(ModState.NotLoaded); } // Update Source if (m.Source == ModSource.Unknown) { if (m.Path.IndexOf(@"\SteamApps\workshop\", StringComparison.OrdinalIgnoreCase) != -1) { m.SetSource(ModSource.SteamWorkshop); } else { // in workshop path but not loaded via steam m.SetSource(ModSource.Manual); } } // Ensure source ID exists if (m.WorkshopID <= 0) { long sourceID; if (m.Source == ModSource.SteamWorkshop && long.TryParse(Path.GetFileName(m.Path), out sourceID)) { m.WorkshopID = sourceID; } else { m.WorkshopID = new ModInfo(m.GetModInfoFile()).PublishedFileID; } } // Fill Date Added if (!m.DateAdded.HasValue) { m.DateAdded = DateTime.Now; } // Check Workshop for infos if (m.WorkshopID != 0) { var publishedID = (ulong)m.WorkshopID; var value = Workshop.GetDetails(publishedID, string.IsNullOrEmpty(m.Description)); if (!m.ManualName) { m.Name = value.m_rgchTitle; } m.DateCreated = DateTimeOffset.FromUnixTimeSeconds(value.m_rtimeCreated).DateTime; m.DateUpdated = DateTimeOffset.FromUnixTimeSeconds(value.m_rtimeUpdated).DateTime; if (value.m_rtimeAddedToUserList > 0) { m.DateAdded = DateTimeOffset.FromUnixTimeSeconds(value.m_rtimeAddedToUserList).DateTime; } //m.Author = SteamWorkshop.GetUsername(value.m_ulSteamIDOwner); //MessageBox.Show(m.Author); // Update directory size m.RealizeSize(value.m_nFileSize); if (m.Size < 0) { m.RealizeSize(Directory.EnumerateFiles(m.Path, "*", SearchOption.AllDirectories).Sum(fileName => new FileInfo(fileName).Length)); } if (string.IsNullOrEmpty(m.Description)) { m.Description = value.m_rgchDescription; } if (value.m_ulSteamIDOwner > 0) { m.Author = Workshop.GetUsername(value.m_ulSteamIDOwner); if (string.IsNullOrEmpty(m.Author)) { m.Author = "Unknown"; } } // Check Workshop for updates if (m.Source == ModSource.SteamWorkshop) { if ( Workshop.GetDownloadStatus((ulong)m.WorkshopID) .HasFlag(EItemState.k_EItemStateNeedsUpdate)) { m.AddState(ModState.UpdateAvailable); } } // Check if it is built for WOTC try { // Parse .XComMod file var modinfo = new ModInfo(m.GetModInfoFile()); m.SetRequiresWOTC(modinfo.RequiresXPACK); } catch (InvalidOperationException) { return; } } else { m.DateCreated = Directory.GetCreationTime(m.Path); m.DateUpdated = Directory.GetLastWriteTime(m.Path); // Update directory size // slow, but necessary ? m.RealizeSize(Directory.EnumerateFiles(m.Path, "*", SearchOption.AllDirectories).Sum(fileName => new FileInfo(fileName).Length)); // Update Name and Description // look for .XComMod file try { // Parse .XComMod file var modinfo = new ModInfo(m.GetModInfoFile()); if (!m.ManualName || m.Name == "") { m.Name = modinfo.Title; } m.Description = modinfo.Description; m.SetRequiresWOTC(modinfo.RequiresXPACK); } catch (InvalidOperationException) { return; } } }
public ModEntry Import(string modDir, ModSource source = ModSource.Unknown) { if (FindByPath(modDir) != null) { // Mod already loaded return(null); } // look for .XComMod file string infoFile = FindModInfo(modDir); if (infoFile == null) { return(null); } var modID = Path.GetFileNameWithoutExtension(infoFile); var isDupe = All.Any(m => m.ID == modID && string.Compare(m.Path, modDir, StringComparison.OrdinalIgnoreCase) == 0); // Parse .XComMod file var modinfo = new ModInfo(infoFile); var mod = new ModEntry { Name = modinfo.Title ?? "Unnamed Mod", ID = modID, Path = modDir, isActive = false, DateAdded = DateTime.Now }; mod.AddState(ModState.New); mod.SetRequiresWOTC(modinfo.RequiresXPACK); mod.SetSource(source); if (source == ModSource.SteamWorkshop) { var s = modDir.Split(Path.DirectorySeparatorChar).Last(); try { mod.WorkshopID = Convert.ToInt64(s); } catch (Exception) { MessageBox.Show( $"A mod could not be loaded because the workshop ID failed to parse.\r\nPlease check that the following directory conforms to valid workshop numbering.\r\n\r\nPath: {modDir}"); return(null); } } AddMod(modinfo.Category, mod); // mark dupes if (isDupe) { foreach (var m in All.Where(m => m.ID == modID)) { m.AddState(ModState.DuplicateID); } } return(mod); }