/// <summary> /// Will initialize internals in a more efficient way that avoids reflection. /// Not required to call, but can be used to warm up ahead of time. /// <br/><br/>NOTE: Calling this warmup which is for a single game, will require you warm up /// other games in the same fashion. Use WarmupAll if you want all games to be warmed. /// </summary> public static void Init() { Loqui.Initialization.SpinUp( new ProtocolDefinition_Bethesda(), new ProtocolDefinition_Skyrim()); LinkInterfaceMapping.AutomaticRegistration = false; LinkInterfaceMapping.Register(new Mutagen.Bethesda.Skyrim.Internals.LinkInterfaceMapping()); InitCustom(); }
/// <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); }
public override void WrapUp() { _defaultVal = _defaultVal.Select(x => FormKeySettingsVM.StripOrigin(x)).ToArray(); Values.SetTo(_defaultVal.Select(x => { return(new FormKeyItemViewModel(x)); })); if (LoquiRegistration.TryGetRegisterByFullName(_typeName, out var regis)) { ScopedTypes = regis.GetterType.AsEnumerable(); } else if (LinkInterfaceMapping.TryGetByFullName(_typeName, out var interfType)) { ScopedTypes = interfType.AsEnumerable(); } else { throw new ArgumentException($"Can't create a formlink control for type: {_typeName}"); } }