Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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;
            }
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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;
                }
            }
        }
Пример #10
0
        /// <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);
            }
        }
Пример #11
0
 public StoryBuilder(Character objCharacter)
 {
     _objCharacter = objCharacter ?? throw new ArgumentNullException(nameof(objCharacter));
     _dicPersistence.TryAdd("metatype", _objCharacter.Metatype.ToLowerInvariant());
     _dicPersistence.TryAdd("metavariant", _objCharacter.Metavariant.ToLowerInvariant());
 }
Пример #12
0
        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);
            }
        }