public SourceString(string strSourceString, string strLanguage = "", CultureInfo objCultureInfo = null, Character objCharacter = null) { Language = !string.IsNullOrEmpty(strLanguage) ? strLanguage : GlobalSettings.Language; CultureInfo = objCultureInfo ?? GlobalSettings.CultureInfo; string strCode = strSourceString ?? string.Empty; Page = 0; int intWhitespaceIndex = strCode.IndexOf(' '); if (intWhitespaceIndex != -1) { strCode = strCode.Substring(0, intWhitespaceIndex); if (intWhitespaceIndex + 1 < strCode.Length) { int.TryParse(strCode.Substring(intWhitespaceIndex + 1), NumberStyles.Integer, GlobalSettings.InvariantCultureInfo, out int intPage); Page = intPage; } } Code = CommonFunctions.LanguageBookShort(strCode, Language, objCharacter); _intHashCode = (Language, CultureInfo, Code, Page).GetHashCode(); if (!s_DicCachedStrings.ContainsKey(Language)) { s_DicCachedStrings.TryAdd(Language, new Tuple <string, string>( LanguageManager.GetString("String_Space", Language), LanguageManager.GetString("String_Page", Language))); } string strSpace = s_DicCachedStrings[Language].Item1; LanguageBookTooltip = CommonFunctions.LanguageBookLong(strCode, Language, objCharacter) + strSpace + s_DicCachedStrings[Language].Item2 + strSpace + Page.ToString(CultureInfo); }
public static CustomActivity StartSyncron(string taskname, CustomActivity parentActivity, CustomActivity.OperationType operationType, string target) { CustomActivity dependencyActivity = new CustomActivity(taskname, parentActivity, operationType, target); s_DictionaryStarts.TryAdd(taskname, s_Time.Elapsed); return(dependencyActivity); }
private static void LoadCharacterSettings() { _intDicLoadedCharacterSettingsLoadedStatus = 0; try { s_DicLoadedCharacterSettings.Clear(); if (Utils.IsDesignerMode || Utils.IsRunningInVisualStudio) { CharacterSettings objNewCharacterSettings = new CharacterSettings(); if (!s_DicLoadedCharacterSettings.TryAdd(GlobalSettings.DefaultCharacterSetting, objNewCharacterSettings)) { objNewCharacterSettings.Dispose(); } return; } IEnumerable <XPathNavigator> xmlSettingsIterator = XmlManager.LoadXPath("settings.xml") .SelectAndCacheExpression("/chummer/settings/setting").Cast <XPathNavigator>(); Parallel.ForEach(xmlSettingsIterator, xmlBuiltInSetting => { CharacterSettings objNewCharacterSettings = new CharacterSettings(); if (!objNewCharacterSettings.Load(xmlBuiltInSetting) || (objNewCharacterSettings.BuildMethodIsLifeModule && !GlobalSettings.LifeModuleEnabled) || !s_DicLoadedCharacterSettings.TryAdd(objNewCharacterSettings.DictionaryKey, objNewCharacterSettings)) { objNewCharacterSettings.Dispose(); } }); 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) || !s_DicLoadedCharacterSettings.TryAdd(objNewCharacterSettings.DictionaryKey, objNewCharacterSettings)) { objNewCharacterSettings.Dispose(); } }); } } finally { _intDicLoadedCharacterSettingsLoadedStatus = 1; } }
/// <summary> /// Get the compiled Xsl Transform of an Xsl file. Will throw exceptions if anything goes awry. /// If we've already compiled the same Xsl Transform before, we'll fetch the cached version of that transform instead of repeating it. /// </summary> /// <param name="strXslFilePath">Absolute path to the Xsl file to be transformed.</param> /// <returns>The compiled Xsl transform of <paramref name="strXslFilePath"/>.</returns> public static XslCompiledTransform GetTransformForFile(string strXslFilePath) { if (!File.Exists(strXslFilePath)) { throw new FileNotFoundException(nameof(strXslFilePath)); } DateTime datLastWriteTimeUtc = File.GetLastWriteTimeUtc(strXslFilePath); XslCompiledTransform objReturn; if (!s_dicCompiledTransforms.TryGetValue( strXslFilePath, out Tuple <DateTime, XslCompiledTransform> tupCachedData) || tupCachedData.Item1 <= datLastWriteTimeUtc) { #if DEBUG objReturn = new XslCompiledTransform(true); #else objReturn = new XslCompiledTransform(); #endif objReturn.Load(strXslFilePath); s_dicCompiledTransforms.Remove(strXslFilePath); s_dicCompiledTransforms.TryAdd( strXslFilePath, new Tuple <DateTime, XslCompiledTransform>(datLastWriteTimeUtc, objReturn)); } else { objReturn = tupCachedData.Item2; } return(objReturn); }
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 if (s_DictionaryStatistics.TryGetValue(taskname, out Tuple <TimeSpan, int> existing)) { s_DictionaryStatistics[taskname] = new Tuple <TimeSpan, int>(existing.Item1 + final, existing.Item2 + 1); } else { s_DictionaryStatistics.TryAdd(taskname, new Tuple <TimeSpan, int>(final, 1)); } } else { Debug.WriteLine("Non started task \"" + taskname + "\" finished"); } return(final); }
/// <summary> /// Get the compiled Xsl Transform of an Xsl file. Will throw exceptions if anything goes awry. /// If we've already compiled the same Xsl Transform before, we'll fetch the cached version of that transform instead of repeating it. /// Uses flag hack method design outlined here to avoid locking: /// https://docs.microsoft.com/en-us/archive/msdn-magazine/2015/july/async-programming-brownfield-async-development /// </summary> /// <param name="blnSync">Flag for whether method should always use synchronous code or not.</param> /// <param name="strXslFilePath">Absolute path to the Xsl file to be transformed.</param> /// <returns>The compiled Xsl transform of <paramref name="strXslFilePath"/>.</returns> private static async Task <XslCompiledTransform> GetTransformForFileCoreAsync(bool blnSync, string strXslFilePath) { if (!File.Exists(strXslFilePath)) { throw new FileNotFoundException(nameof(strXslFilePath)); } DateTime datLastWriteTimeUtc = File.GetLastWriteTimeUtc(strXslFilePath); XslCompiledTransform objReturn; bool blnSuccess; Tuple <DateTime, XslCompiledTransform> tupCachedData; if (blnSync) { // ReSharper disable once MethodHasAsyncOverload blnSuccess = s_dicCompiledTransforms.TryGetValue(strXslFilePath, out tupCachedData); } else { (blnSuccess, tupCachedData) = await s_dicCompiledTransforms.TryGetValueAsync(strXslFilePath); } if (!blnSuccess || tupCachedData.Item1 <= datLastWriteTimeUtc) { #if DEBUG objReturn = new XslCompiledTransform(true); #else objReturn = new XslCompiledTransform(); #endif if (blnSync) { objReturn.Load(strXslFilePath); // ReSharper disable once MethodHasAsyncOverload s_dicCompiledTransforms.Remove(strXslFilePath); // ReSharper disable once MethodHasAsyncOverload s_dicCompiledTransforms.TryAdd( strXslFilePath, new Tuple <DateTime, XslCompiledTransform>(datLastWriteTimeUtc, objReturn)); } else { await Task.Run(() => objReturn.Load(strXslFilePath)); await s_dicCompiledTransforms.RemoveAsync(strXslFilePath); await s_dicCompiledTransforms.TryAddAsync( strXslFilePath, new Tuple <DateTime, XslCompiledTransform>(datLastWriteTimeUtc, objReturn)); } } else { objReturn = tupCachedData.Item2; } return(objReturn); }
private SourceString(string strBookCodeShort, string strBookCodeLong, int intPage, string strLanguage, CultureInfo objCultureInfo) { Language = !string.IsNullOrEmpty(strLanguage) ? strLanguage : GlobalSettings.Language; CultureInfo = objCultureInfo ?? GlobalSettings.CultureInfo; Page = intPage; Code = strBookCodeShort; _intHashCode = (Language, CultureInfo, Code, Page).GetHashCode(); if (!s_DicCachedStrings.ContainsKey(Language)) { s_DicCachedStrings.TryAdd(Language, new Tuple <string, string>( LanguageManager.GetString("String_Space", Language), LanguageManager.GetString("String_Page", Language))); } string strSpace = s_DicCachedStrings[Language].Item1; LanguageBookTooltip = strBookCodeLong + strSpace + s_DicCachedStrings[Language].Item2 + strSpace + Page.ToString(CultureInfo); }
public CursorWait(Control objControl = null, bool blnAppStarting = false) { if (objControl.IsNullOrDisposed()) { _objControl = null; lock (s_ObjApplicationWaitCursorsLock) { ++_intApplicationWaitCursors; if (_intApplicationWaitCursors > 0) { Application.UseWaitCursor = true; } } return; } _objTimer.Start(); Log.Trace("CursorWait for Control \"" + objControl + "\" started with Guid \"" + _guidInstance + "\"."); _objControl = objControl; Form frmControl = _objControl as Form; CursorToUse = blnAppStarting ? Cursors.AppStarting : Cursors.WaitCursor; if (frmControl?.IsMdiChild != false) { if (frmControl != null) { _frmControlTopParent = frmControl.MdiParent; } else if (_objControl is UserControl objUserControl) { _frmControlTopParent = objUserControl.ParentForm; } else { for (Control objLoop = _objControl?.Parent; objLoop != null; objLoop = objLoop.Parent) { if (objLoop is Form objLoopForm) { _frmControlTopParent = objLoopForm; break; } } } } ThreadSafeList <CursorWait> lstNew = new ThreadSafeList <CursorWait>(1); while (_objControl != null && !s_DicWaitingControls.TryAdd(_objControl, lstNew)) { if (!s_DicWaitingControls.TryGetValue(_objControl, out ThreadSafeList <CursorWait> lstExisting)) { continue; } lstNew.Dispose(); CursorWait objLastCursorWait = null; // Need this pattern because the size of lstExisting might change in between fetching lstExisting.Count and lstExisting[] bool blnDoLoop = true; while (blnDoLoop) { blnDoLoop = false; int intIndex = lstExisting.Count - 1; if (intIndex >= 0) { try { objLastCursorWait = lstExisting[intIndex]; } catch (ArgumentOutOfRangeException) { blnDoLoop = true; } } } lstExisting.Add(this); if (blnAppStarting) { if (objLastCursorWait == null) { SetControlCursor(CursorToUse); } else if (objLastCursorWait.CursorToUse == Cursors.WaitCursor) { CursorToUse = Cursors.WaitCursor; } } else if (objLastCursorWait == null || objLastCursorWait.CursorToUse == Cursors.AppStarting) { SetControlCursor(CursorToUse); } return; } // Here for safety purposes if (_objControl.IsNullOrDisposed()) { _objControl = null; _frmControlTopParent = null; lock (s_ObjApplicationWaitCursorsLock) { ++_intApplicationWaitCursors; if (_intApplicationWaitCursors > 0) { Application.UseWaitCursor = true; } } return; } lstNew.Add(this); SetControlCursor(CursorToUse); }
private async ValueTask LoadContent() { using (CustomActivity opLoadMasterindex = Timekeeper.StartSyncron("op_load_frm_masterindex", null, CustomActivity.OperationType.RequestOperation, null)) { _dicCachedNotes.Clear(); foreach (MasterIndexEntry objExistingEntry in _lstItems.Select(x => x.Value)) { objExistingEntry.Dispose(); } _lstItems.Clear(); _lstFileNamesWithItems.Clear(); string strSourceFilter; using (new FetchSafelyFromPool <HashSet <string> >(Utils.StringHashSetPool, out HashSet <string> setValidCodes)) { foreach (XPathNavigator xmlBookNode in (await XmlManager.LoadXPathAsync( "books.xml", _objSelectedSetting.EnabledCustomDataDirectoryPaths)) .SelectAndCacheExpression("/chummer/books/book/code")) { setValidCodes.Add(xmlBookNode.Value); } setValidCodes.IntersectWith(_objSelectedSetting.Books); strSourceFilter = setValidCodes.Count > 0 ? '(' + string.Join(" or ", setValidCodes.Select(x => "source = " + x.CleanXPath())) + ')' : "source"; } using (_ = Timekeeper.StartSyncron("load_frm_masterindex_load_andpopulate_entries", opLoadMasterindex)) { ConcurrentBag <ListItem> lstItemsForLoading = new ConcurrentBag <ListItem>(); using (_ = Timekeeper.StartSyncron("load_frm_masterindex_load_entries", opLoadMasterindex)) { ConcurrentBag <ListItem> lstFileNamesWithItemsForLoading = new ConcurrentBag <ListItem>(); // Prevents locking the UI thread while still benefitting from static scheduling of Parallel.ForEach await Task.WhenAll(_astrFileNames.Select(strFileName => Task.Run(async() => { XPathNavigator xmlBaseNode = await XmlManager.LoadXPathAsync(strFileName, _objSelectedSetting.EnabledCustomDataDirectoryPaths); xmlBaseNode = xmlBaseNode.SelectSingleNodeAndCacheExpression("/chummer"); if (xmlBaseNode == null) { return; } bool blnLoopFileNameHasItems = false; foreach (XPathNavigator xmlItemNode in xmlBaseNode.SelectAndCacheExpression( ".//*[page and " + strSourceFilter + ']')) { blnLoopFileNameHasItems = true; string strName = xmlItemNode.SelectSingleNodeAndCacheExpression("name")?.Value; string strDisplayName = xmlItemNode.SelectSingleNodeAndCacheExpression("translate")?.Value ?? strName ?? xmlItemNode.SelectSingleNodeAndCacheExpression("id")?.Value ?? await LanguageManager.GetStringAsync("String_Unknown"); string strSource = xmlItemNode.SelectSingleNodeAndCacheExpression("source")?.Value; string strPage = xmlItemNode.SelectSingleNodeAndCacheExpression("page")?.Value; string strDisplayPage = xmlItemNode.SelectSingleNodeAndCacheExpression("altpage")?.Value ?? strPage; string strEnglishNameOnPage = xmlItemNode.SelectSingleNodeAndCacheExpression("nameonpage")?.Value ?? strName; string strTranslatedNameOnPage = xmlItemNode.SelectSingleNodeAndCacheExpression("altnameonpage")?.Value ?? strDisplayName; string strNotes = xmlItemNode.SelectSingleNodeAndCacheExpression("altnotes")?.Value ?? xmlItemNode.SelectSingleNodeAndCacheExpression("notes")?.Value; MasterIndexEntry objEntry = new MasterIndexEntry( strDisplayName, strFileName, new SourceString(strSource, strPage, GlobalSettings.DefaultLanguage, GlobalSettings.InvariantCultureInfo), new SourceString(strSource, strDisplayPage, GlobalSettings.Language, GlobalSettings.CultureInfo), strEnglishNameOnPage, strTranslatedNameOnPage); lstItemsForLoading.Add(new ListItem(objEntry, strDisplayName)); if (!string.IsNullOrEmpty(strNotes)) { _dicCachedNotes.TryAdd(objEntry, strNotes); } } if (blnLoopFileNameHasItems) { lstFileNamesWithItemsForLoading.Add(new ListItem(strFileName, strFileName)); } }))); _lstFileNamesWithItems.AddRange(lstFileNamesWithItemsForLoading); } using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_entries", opLoadMasterindex)) { string strSpace = await LanguageManager.GetStringAsync("String_Space"); string strFormat = "{0}" + strSpace + "[{1}]"; Dictionary <string, List <ListItem> > dicHelper = new Dictionary <string, List <ListItem> >(lstItemsForLoading.Count); try { foreach (ListItem objItem in lstItemsForLoading) { if (!(objItem.Value is MasterIndexEntry objEntry)) { continue; } string strKey = objEntry.DisplayName.ToUpperInvariant(); if (dicHelper.TryGetValue(strKey, out List <ListItem> lstExistingItems)) { ListItem objExistingItem = lstExistingItems.Find( x => x.Value is MasterIndexEntry y && objEntry.DisplaySource.Equals(y.DisplaySource)); if (objExistingItem.Value is MasterIndexEntry objLoopEntry) { objLoopEntry.FileNames.UnionWith(objEntry.FileNames); objEntry.Dispose(); } else { using (new FetchSafelyFromPool <List <ListItem> >( Utils.ListItemListPool, out List <ListItem> lstItemsNeedingNameChanges)) { lstItemsNeedingNameChanges.AddRange(lstExistingItems.FindAll( x => x.Value is MasterIndexEntry y && !objEntry.FileNames.IsSubsetOf(y.FileNames))); if (lstItemsNeedingNameChanges.Count == 0) { _lstItems.Add( objItem); // Not using AddRange because of potential memory issues lstExistingItems.Add(objItem); } else { ListItem objItemToAdd = new ListItem( objItem.Value, string.Format(GlobalSettings.CultureInfo, strFormat, objItem.Name, string.Join( ',' + strSpace, objEntry.FileNames))); _lstItems.Add( objItemToAdd); // Not using AddRange because of potential memory issues lstExistingItems.Add(objItemToAdd); foreach (ListItem objToRename in lstItemsNeedingNameChanges) { _lstItems.Remove(objToRename); lstExistingItems.Remove(objToRename); if (!(objToRename.Value is MasterIndexEntry objExistingEntry)) { continue; } objItemToAdd = new ListItem(objToRename.Value, string.Format( GlobalSettings.CultureInfo, strFormat, objExistingEntry.DisplayName, string.Join( ',' + strSpace, objExistingEntry.FileNames))); _lstItems.Add( objItemToAdd); // Not using AddRange because of potential memory issues lstExistingItems.Add(objItemToAdd); } } } } } else { _lstItems.Add(objItem); // Not using AddRange because of potential memory issues List <ListItem> lstHelperItems = Utils.ListItemListPool.Get(); lstHelperItems.Add(objItem); dicHelper.Add(strKey, lstHelperItems); } } } finally { foreach (List <ListItem> lstHelperItems in dicHelper.Values) { Utils.ListItemListPool.Return(lstHelperItems); } } } } using (_ = Timekeeper.StartSyncron("load_frm_masterindex_sort_entries", opLoadMasterindex)) { _lstItems.Sort(CompareListItems.CompareNames); _lstFileNamesWithItems.Sort(CompareListItems.CompareNames); } using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_controls", opLoadMasterindex)) { _lstFileNamesWithItems.Insert(0, new ListItem(string.Empty, await LanguageManager.GetStringAsync("String_All"))); int intOldSelectedIndex = cboFile.SelectedIndex; cboFile.BeginUpdate(); cboFile.PopulateWithListItems(_lstFileNamesWithItems); try { cboFile.SelectedIndex = Math.Max(intOldSelectedIndex, 0); } // For some reason, some unit tests will fire this exception even when _lstFileNamesWithItems is explicitly checked for having enough items catch (ArgumentOutOfRangeException) { cboFile.SelectedIndex = -1; } cboFile.EndUpdate(); lstItems.BeginUpdate(); lstItems.PopulateWithListItems(_lstItems); lstItems.SelectedIndex = -1; lstItems.EndUpdate(); _blnSkipRefresh = false; } } }
/// <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); } }
public StoryBuilder(Character objCharacter) { _objCharacter = objCharacter ?? throw new ArgumentNullException(nameof(objCharacter)); _dicPersistence.TryAdd("metatype", _objCharacter.Metatype.ToLowerInvariant()); _dicPersistence.TryAdd("metavariant", _objCharacter.Metavariant.ToLowerInvariant()); }
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); } }