Ejemplo n.º 1
0
        /// <summary>
        /// Checks if a Keyworded record contains a specific Keyword, by EditorID.
        /// Also looks up that keyword in the given cache.
        /// <br />
        /// Aspects: IKeywordedGetter&lt;IKeywordCommonGetter&gt;
        /// </summary>
        /// <param name="keyworded">Keyworded record to check</param>
        /// <param name="editorID">EditorID of the Keyword to look for</param>
        /// <param name="cache">LinkCache to resolve against</param>
        /// <param name="keyword">Keyword record retrieved, if keyworded record does contain</param>
        /// <param name="stringComparison">
        /// What string comparison type to use.<br />
        /// By default EditorIDs are case insensitive.
        /// </param>
        /// <returns>True if the Keyworded record contains a Keyword link that points to a winning Keyword record /w the given EditorID</returns>
        public static bool TryResolveKeyword <TKeyword>(
            this IKeywordedGetter <TKeyword> keyworded,
            string editorID,
            ILinkCache cache,
            [MaybeNullWhen(false)] out TKeyword keyword,
            StringComparison stringComparison = StringComparison.OrdinalIgnoreCase)
            where TKeyword : class, IKeywordCommonGetter
        {
            // ToDo
            // Consider EDID link cache systems if/when available
            if (keyworded.Keywords == null)
            {
                keyword = default;
                return(false);
            }
            foreach (var keywordForm in keyworded.Keywords.Select(link => link.FormKey))
            {
                if (cache.TryResolve <TKeyword>(keywordForm, out keyword) &&
                    (keyword.EditorID?.Equals(editorID, stringComparison) ?? false))
                {
                    return(true);
                }
            }

            keyword = default;
            return(false);
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Attempts to locate link winning target record in given Link Cache.
 /// </summary>
 /// <param name="link">FormLink to resolve</param>
 /// <param name="cache">Link Cache to resolve against</param>
 /// <param name="majorRecord">Located record if successful</param>
 /// <returns>True if link was resolved and a record was retrieved</returns>
 /// <typeparam name="TMajor">Major Record type to resolve to</typeparam>
 public static bool TryResolve <TMajor>(this IFormLinkGetter link, ILinkCache cache, [MaybeNullWhen(false)] out TMajor majorRecord)
     where TMajor : class, IMajorRecordCommonGetter
 {
     if (!link.FormKeyNullable.TryGet(out var formKey))
     {
         majorRecord = default;
         return(false);
     }
     return(cache.TryResolve(formKey, out majorRecord));
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Attempts to locate link's winning target record in given Link Cache.
 /// </summary>
 /// <param name="link">Link to resolve</param>
 /// <param name="cache">Link Cache to resolve against</param>
 /// <param name="majorRecord">Major Record if located</param>
 /// <returns>True if successful in linking to record</returns>
 /// <typeparam name="TMajor">Major Record type to resolve to</typeparam>
 public static bool TryResolve <TMajor>(this IFormLinkGetter <TMajor> link, ILinkCache cache, [MaybeNullWhen(false)] out TMajor majorRecord)
     where TMajor : class, IMajorRecordGetter
 {
     if (link.FormKeyNullable is not {
     } formKey)
     {
         majorRecord = default;
         return(false);
     }
     return(cache.TryResolve <TMajor>(formKey, out majorRecord));
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Checks if a Keyworded record contains a specific Keyword, by FormKey.
 /// Also looks up that keyword in the given cache. <br />
 /// <br />
 /// Note that this function only succeeds if the record contains the keyword,
 /// and the cache found it as well. <br />
 /// <br />
 /// It is possible that the record contains the keyword, but it could not be found
 /// by the cache.
 /// <br />
 /// Aspects: IKeywordedGetter&lt;IKeywordCommonGetter&gt;
 /// </summary>
 /// <param name="keyworded">Keyworded record to check</param>
 /// <param name="keywordKey">FormKey of the Keyword record to look for</param>
 /// <param name="cache">LinkCache to resolve against</param>
 /// <param name="keyword">Keyword record retrieved, if keyworded record does contain</param>
 /// <returns>True if the Keyworded record contains a Keyword link /w the given FormKey</returns>
 public static bool TryResolveKeyword <TKeyword>(
     this IKeywordedGetter <TKeyword> keyworded,
     FormKey keywordKey,
     ILinkCache cache,
     [MaybeNullWhen(false)] out TKeyword keyword)
     where TKeyword : class, IKeywordCommonGetter
 {
     if (!keyworded.Keywords?.Any(x => x.FormKey == keywordKey) ?? true)
     {
         keyword = default;
         return(false);
     }
     return(cache.TryResolve(keywordKey, out keyword));
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Duplicates records into a given mod 'modToDuplicateInto', which originated from target ModKey 'modKeyToDuplicateFrom'.<br />
        /// Only considers records that are currently within the target modToDuplicateInto, which are then duplicated. <br/>
        /// Records from the modKeyToDuplicateFrom that are not within or referenced by records in the target mod are skipped.<br />
        /// <br />
        /// End result will be that all records that the given modToDuplicateInto contains or references that originate from the target modKeyToDuplicateFrom will be duplicated in
        /// and replace the records they duplicated.  No references to the modKeyToDuplicateFrom will remain.
        /// </summary>
        /// <typeparam name="TMod"></typeparam>
        /// <typeparam name="TModGetter"></typeparam>
        /// <param name="modToDuplicateInto">Mod to duplicate into and originate new records from</param>
        /// <param name="linkCache">LinkCache for lookup</param>
        /// <param name="modKeyToDuplicateFrom">ModKey to search modToDuplicateInto for, and duplicate records that originate from modKeyToDuplicateFrom</param>
        /// <param name="mapping">Out parameter to store the resulting duplication mappings that were made</param>
        /// <param name="typesToInspect">
        /// Types to iterate and look at within modToDuplicateInto for references to modKeyToDuplicateFrom<br />
        /// Only use if you know specifically the types that can reference modKeyToDuplicateFrom, and want a little bit of speed
        /// by not checking uninteresting records.
        /// </param>
        public static void DuplicateFromOnlyReferenced <TMod, TModGetter>(
            this TMod modToDuplicateInto,
            ILinkCache <TMod, TModGetter> linkCache,
            ModKey modKeyToDuplicateFrom,
            out Dictionary <FormKey, FormKey> mapping,
            params Type[] typesToInspect)
            where TModGetter : class, IModGetter
            where TMod : class, TModGetter, IMod
        {
            if (modKeyToDuplicateFrom == modToDuplicateInto.ModKey)
            {
                throw new ArgumentException("Cannot pass the target mod's Key as the one to extract and self contain");
            }

            // Compile list of things to duplicate
            HashSet <IFormLinkGetter> identifiedLinks = new();
            HashSet <FormKey>         passedLinks     = new();
            var implicits = Implicits.Get(modToDuplicateInto.GameRelease);

            void AddAllLinks(IFormLinkGetter link)
            {
                if (link.FormKey.IsNull)
                {
                    return;
                }
                if (!passedLinks.Add(link.FormKey))
                {
                    return;
                }
                if (implicits.RecordFormKeys.Contains(link.FormKey))
                {
                    return;
                }

                if (link.FormKey.ModKey == modKeyToDuplicateFrom)
                {
                    identifiedLinks.Add(link);
                }

                if (!linkCache.TryResolve(link.FormKey, link.Type, out var linkRec))
                {
                    return;
                }

                foreach (var containedLink in linkRec.ContainedFormLinks)
                {
                    if (containedLink.FormKey.ModKey != modKeyToDuplicateFrom)
                    {
                        continue;
                    }
                    AddAllLinks(containedLink);
                }
            }

            var enumer = typesToInspect == null || typesToInspect.Length == 0
                ? modToDuplicateInto.EnumerateMajorRecords()
                : typesToInspect.SelectMany(x => modToDuplicateInto.EnumerateMajorRecords(x));

            foreach (var rec in enumer)
            {
                AddAllLinks(new FormLinkInformation(rec.FormKey, rec.Registration.GetterType));
            }

            // Duplicate in the records
            mapping = new();
            foreach (var identifiedRec in identifiedLinks)
            {
                if (!linkCache.TryResolveContext(identifiedRec.FormKey, identifiedRec.Type, out var rec))
                {
                    throw new KeyNotFoundException($"Could not locate record to make self contained: {identifiedRec}");
                }

                var dup = rec.DuplicateIntoAsNewRecord(modToDuplicateInto, rec.Record.EditorID);
                mapping[rec.Record.FormKey] = dup.FormKey;

                // ToDo
                // Move this out of loop, and remove off a new IEnumerable<IFormLinkGetter> call
                modToDuplicateInto.Remove(identifiedRec.FormKey, identifiedRec.Type);
            }

            // Remap links
            modToDuplicateInto.RemapLinks(mapping);
        }