/// <summary> /// Looks up a given FormKey to try to locate the target record. /// /// Will only look into the Groups that are applicable to the given type. /// </summary> /// <param name="formKey">FormKey to search for</param> /// <param name="majorRec">MajorRecord if found</param> /// <typeparam name="TMajor">MajorRecod type or interface to look for</typeparam> /// <returns>True if record was found</returns> /// <exception cref="ArgumentException"> /// An unexpected TMajor type will throw an exception. /// Unexpected types include: /// - Major Record Types that are not part of this game type. (Querying for Oblivion records on a Skyrim mod) /// - A setter type is requested from a getter only object. /// </exception> public bool TryLookup <TMajor>(FormKey formKey, [MaybeNullWhen(false)] out TMajor majorRec) where TMajor : class, IMajorRecordCommonGetter { if (!_hasAny) { majorRec = default; return(false); } lock (this._loadOrderMajorRecords) { // Get cache object by type if (!this._loadOrderMajorRecords.TryGetValue(typeof(TMajor), out InternalTypedCache cache)) { cache = new InternalTypedCache(); if (typeof(TMajor).Equals(typeof(IMajorRecordCommon)) || typeof(TMajor).Equals(typeof(IMajorRecordCommonGetter))) { this._loadOrderMajorRecords[typeof(IMajorRecordCommon)] = cache; this._loadOrderMajorRecords[typeof(IMajorRecordCommonGetter)] = cache; } else if (LoquiRegistration.TryGetRegister(typeof(TMajor), out var registration)) { this._loadOrderMajorRecords[registration.ClassType] = cache; this._loadOrderMajorRecords[registration.GetterType] = cache; this._loadOrderMajorRecords[registration.SetterType] = cache; if (registration.InternalGetterType != null) { this._loadOrderMajorRecords[registration.InternalGetterType] = cache; } if (registration.InternalSetterType != null) { this._loadOrderMajorRecords[registration.InternalSetterType] = cache; } } else { var interfaceMappings = LinkInterfaceMapping.InterfaceToObjectTypes(_gameMode); if (!interfaceMappings.TryGetValue(typeof(TMajor), out var objs)) { throw new ArgumentException($"A lookup was queried for an unregistered type: {typeof(TMajor).Name}"); } this._loadOrderMajorRecords[typeof(TMajor)] = cache; } } // Check for record if (cache.Dictionary.TryGetValue(formKey, out var majorRecObj)) { majorRec = (majorRecObj as TMajor) !; return(majorRec != null); } if (cache.Depth >= this._loadOrder.Count) { majorRec = default !;
/// <summary> /// Constructs a LoadOrderLinkCache around a target load order /// </summary> /// <param name="loadOrder">LoadOrder to resolve against when linking</param> public ImmutableLoadOrderLinkCache(IEnumerable <TModGetter> loadOrder) { this._listedOrder = loadOrder.ToList(); this._priorityOrder = _listedOrder.Reverse().ToList(); var firstMod = _listedOrder.FirstOrDefault(); this._hasAny = firstMod != null; // ToDo // Upgrade to bounce off ModInstantiator systems this._gameCategory = firstMod?.GameRelease.ToCategory() ?? GameCategory.Oblivion; this._linkInterfaces = LinkInterfaceMapping.InterfaceToObjectTypes(_gameCategory); }
private IReadOnlyCache <IModContext <TMod, IMajorRecordCommon, IMajorRecordCommonGetter>, FormKey> GetContextCache(Type type) { if (!_contexts.TryGetValue(type, out var cache)) { if (type.Equals(typeof(IMajorRecordCommon)) || type.Equals(typeof(IMajorRecordCommonGetter))) { cache = ConstructContextCache(type); _contexts[typeof(IMajorRecordCommon)] = cache; _contexts[typeof(IMajorRecordCommonGetter)] = cache; } else if (LoquiRegistration.TryGetRegister(type, out var registration)) { cache = ConstructContextCache(type); _contexts[registration.ClassType] = cache; _contexts[registration.GetterType] = cache; _contexts[registration.SetterType] = cache; if (registration.InternalGetterType != null) { _contexts[registration.InternalGetterType] = cache; } if (registration.InternalSetterType != null) { _contexts[registration.InternalSetterType] = cache; } } else { var interfaceMappings = LinkInterfaceMapping.InterfaceToObjectTypes(_sourceMod.GameRelease.ToCategory()); if (!interfaceMappings.TryGetValue(type, out var objs)) { throw new ArgumentException($"A lookup was queried for an unregistered type: {type.Name}"); } var majorRecords = new Cache <IModContext <TMod, IMajorRecordCommon, IMajorRecordCommonGetter>, FormKey>(x => x.Record.FormKey); foreach (var objType in objs) { majorRecords.Set(GetContextCache(LoquiRegistration.GetRegister(objType).GetterType).Items); } _contexts[type] = majorRecords; cache = majorRecords; } } return(cache); }