Exemplo n.º 1
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="TMod">Mod setter type that can be overridden into</typeparam>
 /// <typeparam name="TMajorSetter">Major Record setter type to resolve to</typeparam>
 /// <typeparam name="TMajorGetter">Major Record getter type to resolve to</typeparam>
 public static bool TryResolveContext <TMod, TMajorSetter, TMajorGetter>(
     this IFormLink <TMajorGetter> link,
     ILinkCache <TMod> cache,
     [MaybeNullWhen(false)] out IModContext <TMod, TMajorSetter, TMajorGetter> majorRecord)
     where TMod : class, IContextMod <TMod>
     where TMajorSetter : class, IMajorRecordCommon, TMajorGetter
     where TMajorGetter : class, IMajorRecordCommonGetter
 {
     if (!link.FormKeyNullable.TryGet(out var formKey))
     {
         majorRecord = default;
         return(false);
     }
     return(cache.TryResolveContext <TMajorSetter, TMajorGetter>(formKey, out majorRecord));
 }
Exemplo n.º 2
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="TMod">Mod setter type that can be overridden into</typeparam>
 /// <typeparam name="TModGetter">Mod getter type that can be overridden into</typeparam>
 /// <typeparam name="TMajor">Major Record setter type to resolve to</typeparam>
 /// <typeparam name="TMajorGetter">Major Record getter type to resolve to</typeparam>
 public static bool TryResolveContext <TMod, TModGetter, TMajor, TMajorGetter>(
     this IFormLinkGetter <TMajorGetter> link,
     ILinkCache <TMod, TModGetter> cache,
     [MaybeNullWhen(false)] out IModContext <TMod, TModGetter, TMajor, TMajorGetter> majorRecord)
     where TModGetter : class, IModGetter
     where TMod : class, TModGetter, IContextMod <TMod, TModGetter>
     where TMajor : class, IMajorRecord, TMajorGetter
     where TMajorGetter : class, IMajorRecordGetter
 {
     if (link.FormKeyNullable is not {
     } formKey)
     {
         majorRecord = default;
         return(false);
     }
     return(cache.TryResolveContext <TMajor, TMajorGetter>(formKey, out majorRecord));
 }
Exemplo n.º 3
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);
        }