public static TimeSpan Finish(string taskname) { TimeSpan final = TimeSpan.Zero; if (s_DictionaryStarts.TryRemove(taskname, out TimeSpan objStartTimeSpan)) { final = s_Time.Elapsed - objStartTimeSpan; #if DEBUG string strLogEntry = string.Format(GlobalSettings.InvariantCultureInfo, "Task \"{0}\" finished in {1}", taskname, final); //Log.Trace(strLogEntry); Debug.WriteLine(strLogEntry); #endif s_DictionaryStatistics.AddOrUpdate(taskname, x => new Tuple <TimeSpan, int>(final, 1), (x, y) => new Tuple <TimeSpan, int>( y.Item1 + final, y.Item2 + 1)); } else { Debug.WriteLine("Non started task \"" + taskname + "\" finished"); } return(final); }
/// <summary> /// Generates a character cache, which prevents us from repeatedly loading XmlNodes or caching a full character. /// </summary> /// <param name="strFile"></param> private TreeNode CacheCharacters(string strFile) { if (!File.Exists(strFile)) { Program.MainForm.ShowMessageBox( this, string.Format(GlobalSettings.CultureInfo, LanguageManager.GetString("Message_File_Cannot_Be_Accessed"), strFile)); return(null); } using (ThreadSafeList <XPathNavigator> lstCharacterXmlStatblocks = new ThreadSafeList <XPathNavigator>(3)) { try { using (ZipArchive zipArchive = ZipFile.Open(strFile, ZipArchiveMode.Read, Encoding.GetEncoding(850))) { Parallel.ForEach(zipArchive.Entries, entry => { string strEntryFullName = entry.FullName; if (strEntryFullName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase) && strEntryFullName.StartsWith("statblocks_xml", StringComparison.Ordinal)) { // If we run into any problems loading the character cache, fail out early. try { XPathDocument xmlSourceDoc; using (StreamReader sr = new StreamReader(entry.Open(), true)) using (XmlReader objXmlReader = XmlReader.Create(sr, GlobalSettings.SafeXmlReaderSettings)) xmlSourceDoc = new XPathDocument(objXmlReader); XPathNavigator objToAdd = xmlSourceDoc.CreateNavigator(); // ReSharper disable once AccessToDisposedClosure lstCharacterXmlStatblocks.Add(objToAdd); } // If we run into any problems loading the character cache, fail out early. catch (IOException) { Utils.BreakIfDebug(); } catch (XmlException) { Utils.BreakIfDebug(); } } else if (strEntryFullName.StartsWith("images", StringComparison.Ordinal) && strEntryFullName.Contains('.')) { string strKey = Path.GetFileName(strEntryFullName); using (Bitmap bmpMugshot = new Bitmap(entry.Open(), true)) { Bitmap bmpNewMugshot = bmpMugshot.PixelFormat == PixelFormat.Format32bppPArgb ? bmpMugshot.Clone() as Bitmap // Clone makes sure file handle is closed : bmpMugshot.ConvertPixelFormat(PixelFormat.Format32bppPArgb); while (!_dicImages.TryAdd(strKey, bmpNewMugshot)) { if (_dicImages.TryRemove(strKey, out Bitmap bmpOldMugshot)) { bmpOldMugshot?.Dispose(); } } } } }); } } catch (IOException) { Program.MainForm.ShowMessageBox( this, string.Format(GlobalSettings.CultureInfo, LanguageManager.GetString("Message_File_Cannot_Be_Accessed"), strFile)); return(null); } catch (NotSupportedException) { Program.MainForm.ShowMessageBox( this, string.Format(GlobalSettings.CultureInfo, LanguageManager.GetString("Message_File_Cannot_Be_Accessed"), strFile)); return(null); } catch (UnauthorizedAccessException) { Program.MainForm.ShowMessageBox( this, LanguageManager.GetString("Message_Insufficient_Permissions_Warning")); return(null); } string strFileText = strFile.CheapReplace(Utils.GetStartupPath, () => '<' + Application.ProductName + '>'); TreeNode nodRootNode = new TreeNode { Text = strFileText, ToolTipText = strFileText }; XPathNavigator xmlMetatypesDocument = XmlManager.LoadXPath("metatypes.xml"); foreach (XPathNavigator xmlCharacterDocument in lstCharacterXmlStatblocks) { XPathNavigator xmlBaseCharacterNode = xmlCharacterDocument.SelectSingleNode("/document/public/character"); if (xmlBaseCharacterNode != null) { HeroLabCharacterCache objCache = new HeroLabCharacterCache { PlayerName = xmlBaseCharacterNode.SelectSingleNode("@playername")?.Value ?? string.Empty }; string strNameString = xmlBaseCharacterNode.SelectSingleNode("@name")?.Value ?? string.Empty; objCache.CharacterId = strNameString; if (!string.IsNullOrEmpty(strNameString)) { int intAsIndex = strNameString.IndexOf(" as ", StringComparison.Ordinal); if (intAsIndex != -1) { objCache.CharacterName = strNameString.Substring(0, intAsIndex); objCache.CharacterAlias = strNameString.Substring(intAsIndex).TrimStart(" as ").Trim('\''); } else { objCache.CharacterName = strNameString; } } string strRaceString = xmlBaseCharacterNode.SelectSingleNode("race/@name")?.Value; if (strRaceString == "Metasapient") { strRaceString = "A.I."; } if (!string.IsNullOrEmpty(strRaceString)) { foreach (XPathNavigator xmlMetatype in xmlMetatypesDocument.Select( "/chummer/metatypes/metatype")) { string strMetatypeName = xmlMetatype.SelectSingleNode("name")?.Value ?? string.Empty; if (strMetatypeName == strRaceString) { objCache.Metatype = strMetatypeName; objCache.Metavariant = "None"; break; } foreach (XPathNavigator xmlMetavariant in xmlMetatype.SelectAndCacheExpression("metavariants/metavariant")) { string strMetavariantName = xmlMetavariant.SelectSingleNode("name")?.Value ?? string.Empty; if (strMetavariantName == strRaceString) { objCache.Metatype = strMetatypeName; objCache.Metavariant = strMetavariantName; break; } } } } objCache.Description = xmlBaseCharacterNode.SelectSingleNode("personal/description")?.Value; objCache.Karma = xmlBaseCharacterNode.SelectSingleNode("karma/@total")?.Value ?? "0"; objCache.Essence = xmlBaseCharacterNode .SelectSingleNode("attributes/attribute[@name = \"Essence\"]/@text")?.Value; objCache.BuildMethod = xmlBaseCharacterNode.SelectSingleNode("creation/bp/@total")?.Value == "25" ? nameof(CharacterBuildMethod.Priority) : nameof(CharacterBuildMethod.Karma); objCache.Created = objCache.Karma != "0"; if (!objCache.Created) { XPathNodeIterator xmlJournalEntries = xmlBaseCharacterNode.SelectAndCacheExpression("journals/journal"); if (xmlJournalEntries?.Count > 1) { objCache.Created = true; } else if (xmlJournalEntries?.Count == 1 && xmlJournalEntries.Current?.SelectSingleNode("@name")?.Value != "Title") { objCache.Created = true; } } string strImageString = xmlBaseCharacterNode.SelectSingleNode("images/image/@filename")?.Value; if (!string.IsNullOrEmpty(strImageString) && _dicImages.TryGetValue(strImageString, out Bitmap objTemp)) { objCache.Mugshot = objTemp; } objCache.FilePath = strFile; TreeNode objNode = new TreeNode { Text = CalculatedName(objCache), ToolTipText = strFile.CheapReplace(Utils.GetStartupPath, () => '<' + Application.ProductName + '>') }; nodRootNode.Nodes.Add(objNode); _lstCharacterCache.Add(objCache); objNode.Tag = _lstCharacterCache.IndexOf(objCache); } } nodRootNode.Expand(); return(nodRootNode); } }
private static void LoadCustomCharacterSettings() { // Don't attempt to load custom character settings if we're still loading all settings if (Interlocked.CompareExchange(ref _intDicLoadedCharacterSettingsLoadedStatus, 1, 2) <= 1) { return; } try { using (LockingDictionary <string, CharacterSettings> dicNewLoadedCharacterSettings = new LockingDictionary <string, CharacterSettings>()) { string strSettingsPath = Path.Combine(Utils.GetStartupPath, "settings"); if (Directory.Exists(strSettingsPath)) { Parallel.ForEach(Directory.EnumerateFiles(strSettingsPath, "*.xml"), strSettingsFilePath => { string strSettingName = Path.GetFileName(strSettingsFilePath); CharacterSettings objNewCharacterSettings = new CharacterSettings(); if (!objNewCharacterSettings.Load(strSettingName, false) || (objNewCharacterSettings.BuildMethodIsLifeModule && !GlobalSettings.LifeModuleEnabled) // ReSharper disable once AccessToDisposedClosure || !dicNewLoadedCharacterSettings.TryAdd(objNewCharacterSettings.DictionaryKey, objNewCharacterSettings)) { objNewCharacterSettings.Dispose(); } }); } using (new FetchSafelyFromPool <HashSet <string> >(Utils.StringHashSetPool, out HashSet <string> setRemovedSettingsKeys)) { foreach (CharacterSettings objExistingSettings in s_DicLoadedCharacterSettings.Values.ToList()) { if (objExistingSettings.BuiltInOption) { continue; } if (!dicNewLoadedCharacterSettings.TryRemove(objExistingSettings.DictionaryKey, out CharacterSettings objNewSettings)) { setRemovedSettingsKeys.Add(objExistingSettings.DictionaryKey); } else { objExistingSettings.CopyValues(objNewSettings); objNewSettings.Dispose(); } } foreach (CharacterSettings objNewSettings in dicNewLoadedCharacterSettings.Values) { if (!s_DicLoadedCharacterSettings.TryAdd(objNewSettings.DictionaryKey, objNewSettings)) { objNewSettings.Dispose(); } } foreach (string strSettingToRemove in setRemovedSettingsKeys) { CharacterSettings objSettingsToDelete = s_DicLoadedCharacterSettings[strSettingToRemove]; try { Lazy <string> strBestMatchNewSettingsKey = new Lazy <string>(() => { int intBestScore = int.MinValue; string strReturn = string.Empty; foreach (CharacterSettings objExistingSettings in s_DicLoadedCharacterSettings.Values) { if (setRemovedSettingsKeys.Contains(objExistingSettings.DictionaryKey)) { continue; } // ReSharper disable once AccessToDisposedClosure int intLoopScore = CalculateCharacterSettingsMatchScore(objSettingsToDelete, objExistingSettings); if (intLoopScore > intBestScore) { intBestScore = intLoopScore; strReturn = objExistingSettings.DictionaryKey; } } return(strReturn); }); foreach (Character objCharacter in Program.OpenCharacters) { if (objCharacter.SettingsKey == objSettingsToDelete.DictionaryKey) { objCharacter.SettingsKey = strBestMatchNewSettingsKey.Value; } } } finally { s_DicLoadedCharacterSettings.Remove(objSettingsToDelete.DictionaryKey); objSettingsToDelete.Dispose(); } } } } } finally { Interlocked.Increment(ref _intDicLoadedCharacterSettingsLoadedStatus); } }