static MajorRecordInstantiator() { if (!LoquiRegistration.TryGetRegister(typeof(TMajor), out var regis)) { throw new ArgumentException(); } var ctorInfo = regis.ClassType.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic) .Where(c => { var param = c.GetParameters(); if (param.Length != 2) { return(false); } if (param[0].ParameterType != typeof(FormKey)) { return(false); } if (param[1].ParameterType != typeof(GameRelease)) { return(false); } return(true); }) .First(); var paramInfo = ctorInfo.GetParameters(); ParameterExpression formKey = Expression.Parameter(typeof(FormKey), "formKey"); ParameterExpression gameRelease = Expression.Parameter(typeof(GameRelease), "gameRelease"); NewExpression newExp = Expression.New(ctorInfo, formKey, gameRelease); LambdaExpression lambda = Expression.Lambda(typeof(Func <FormKey, GameRelease, TMajor>), newExp, formKey, gameRelease); Activator = (Func <FormKey, GameRelease, TMajor>)lambda.Compile(); }
public bool TryGetTranslator(Type?t, out GetResponse <ObjTransl> not) { if (t == null) { not = NullTranslationItem; return(true); } if (typeDict.TryGetValue(t, out var item)) { not = item; return(true); } if (LoquiRegistration.TryGetRegister(t, out var regis)) { var loquiTypes = new Type[] { regis.ClassType }; var xmlConverterGenType = loquiTranslation.MakeGenericType(loquiTypes); var xmlCaster = GetCaster(xmlConverterGenType, regis.ClassType); item = GetResponse <ObjTransl> .Succeed(xmlCaster); typeDict[t] = item; not = item; return(true); } if (t.IsEnum || (Nullable.GetUnderlyingType(t)?.IsEnum ?? false)) { var implType = enumTranslation.MakeGenericType(Nullable.GetUnderlyingType(t) ?? t); var caster = GetCaster(implType, t); not = SetTranslator(caster, t); return(true); } foreach (var genType in GenericTypes) { var defs = genType.GetGenericArguments(); if (defs.Length != 1) { continue; } var def = defs[0]; if (t.InheritsFrom(def)) { var implType = genType.MakeGenericType(t); var caster = GetCaster(implType, t); not = SetTranslator(caster, t); return(true); } } not = default; return(false); }
private static Type GetRecordType(Type t) { if (LoquiRegistration.TryGetRegister(t, out var regis)) { return(regis.ClassType); } return(t); }
static ModInstantiator() { if (!LoquiRegistration.TryGetRegister(typeof(TMod), out var regis)) { throw new ArgumentException(); } Activator = ModInstantiatorReflection.GetActivator <TMod>(regis); Importer = ModInstantiatorReflection.GetImporter <TMod>(regis); }
/// <inheritdoc /> public bool TryResolve(FormKey formKey, Type type, [MaybeNullWhen(false)] out IMajorRecordCommonGetter majorRec) { if (!_hasAny || formKey.IsNull) { majorRec = default; return(false); } DepthCache <IMajorRecordCommonGetter> cache; lock (this._winningRecords) { // Get cache object by type if (!this._winningRecords.TryGetValue(type, out cache)) { cache = new DepthCache <IMajorRecordCommonGetter>(); if (type.Equals(typeof(IMajorRecordCommon)) || type.Equals(typeof(IMajorRecordCommonGetter))) { this._winningRecords[typeof(IMajorRecordCommon)] = cache; this._winningRecords[typeof(IMajorRecordCommonGetter)] = cache; } else if (LoquiRegistration.TryGetRegister(type, out var registration)) { this._winningRecords[registration.ClassType] = cache; this._winningRecords[registration.GetterType] = cache; this._winningRecords[registration.SetterType] = cache; if (registration.InternalGetterType != null) { this._winningRecords[registration.InternalGetterType] = cache; } if (registration.InternalSetterType != null) { this._winningRecords[registration.InternalSetterType] = cache; } } else { if (!_linkInterfaces.TryGetValue(type, out var objs)) { throw new ArgumentException($"A lookup was queried for an unregistered type: {type.Name}"); } this._winningRecords[type] = cache; } } } lock (cache) { // Check for record if (cache.TryGetValue(formKey, out majorRec)) { return(true); } if (IsPastDepth(cache.Depth)) { majorRec = default !;
/// <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 !;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is not Type type) { return(Binding.DoNothing); } if (LoquiRegistration.TryGetRegister(type, out var registration)) { return(registration.ProtocolKey.Namespace); } return(string.Empty); }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is not Type type) { return(Binding.DoNothing); } if (LoquiRegistration.TryGetRegister(type, out var register)) { return(register.ClassType.Name); } return(type.Name); }
static MajorRecordPrinter() { var t = typeof(TMajor); if (LoquiRegistration.TryGetRegister(t, out var regis)) { _TypeString = $"{regis.ProtocolKey.Namespace}.{t.Name}"; } else { _TypeString = t.Name; } }
static MajorRecordInstantiator() { if (!LoquiRegistration.TryGetRegister(typeof(T), out var regis)) { throw new ArgumentException(); } var ctorInfo = regis.ClassType.GetConstructors() .Where(c => c.GetParameters().Length == 1) .Where(c => c.GetParameters()[0].ParameterType == typeof(FormKey)) .First(); var paramInfo = ctorInfo.GetParameters(); ParameterExpression param = Expression.Parameter(typeof(FormKey), "formKey"); NewExpression newExp = Expression.New(ctorInfo, param); LambdaExpression lambda = Expression.Lambda(typeof(MajorRecordActivator <T>), newExp, param); Activator = (MajorRecordActivator <T>)lambda.Compile(); }
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); }
internal static IEnumerable <IModContext <IOblivionMod, IOblivionModGetter, IMajorRecordCommon, IMajorRecordCommonGetter> > EnumerateMajorRecordContexts( this IListGroupGetter <ICellBlockGetter> cellBlocks, ILinkCache linkCache, Type type, ModKey modKey, IModContext?parent, bool throwIfUnknown) { foreach (var readOnlyBlock in cellBlocks.Records) { var blockNum = readOnlyBlock.BlockNumber; var blockModified = readOnlyBlock.LastModified; var blockContext = new ModContext <ICellBlockGetter>( modKey: modKey, parent: parent, record: readOnlyBlock); foreach (var readOnlySubBlock in readOnlyBlock.SubBlocks) { var subBlockNum = readOnlySubBlock.BlockNumber; var subBlockModified = readOnlySubBlock.LastModified; var subBlockContext = new ModContext <ICellSubBlockGetter>( modKey: modKey, parent: blockContext, record: readOnlySubBlock); foreach (var readOnlyCell in readOnlySubBlock.Cells) { Func <IOblivionMod, ICellGetter, bool, string?, ICell> cellGetter = (mod, copyCell, dup, edid) => { var formKey = copyCell.FormKey; var retrievedBlock = mod.Cells.Records.FirstOrDefault(x => x.BlockNumber == blockNum); if (retrievedBlock == null) { retrievedBlock = new CellBlock() { BlockNumber = blockNum, GroupType = GroupTypeEnum.InteriorCellBlock, LastModified = blockModified, }; mod.Cells.Records.Add(retrievedBlock); } var subBlock = retrievedBlock.SubBlocks.FirstOrDefault(x => x.BlockNumber == subBlockNum); if (subBlock == null) { subBlock = new CellSubBlock() { BlockNumber = subBlockNum, GroupType = GroupTypeEnum.InteriorCellSubBlock, LastModified = subBlockModified, }; retrievedBlock.SubBlocks.Add(subBlock); } var cell = subBlock.Cells.FirstOrDefault(cell => cell.FormKey == formKey); if (cell == null) { if (dup) { cell = copyCell.Duplicate(mod.GetNextFormKey(edid), CellCopyMask); } else { cell = copyCell.DeepCopy(CellCopyMask); } subBlock.Cells.Add(cell); } return(cell); }; if (LoquiRegistration.TryGetRegister(type, out var regis) && regis.ClassType == typeof(Cell)) { yield return(new ModContext <IOblivionMod, IOblivionModGetter, IMajorRecordCommon, IMajorRecordCommonGetter>( modKey: modKey, record: readOnlyCell, getOrAddAsOverride: (m, r) => cellGetter(m, (ICellGetter)r, false, default(string?)), duplicateInto: (m, r, e) => cellGetter(m, (ICellGetter)r, true, e), parent: subBlockContext)); } else { foreach (var con in CellCommon.Instance.EnumerateMajorRecordContexts( readOnlyCell, linkCache, type, modKey, subBlockContext, throwIfUnknown, (m, c) => cellGetter(m, c, false, default(string?)), (m, c, e) => cellGetter(m, c, true, e))) { yield return(con); } } } } } }
internal static IEnumerable <IModContext <IFallout4Mod, IMajorRecordCommon, IMajorRecordCommonGetter> > EnumerateMajorRecordContexts( this IReadOnlyList <IWorldspaceBlockGetter> worldspaceBlocks, IWorldspaceGetter worldspace, ILinkCache linkCache, Type type, ModKey modKey, IModContext?parent, bool throwIfUnknown, Func <IFallout4Mod, IWorldspaceGetter, IWorldspace> getOrAddAsOverride, Func <IFallout4Mod, IWorldspaceGetter, string?, IWorldspace> duplicateInto) { foreach (var readOnlyBlock in worldspaceBlocks) { var blockNumX = readOnlyBlock.BlockNumberX; var blockNumY = readOnlyBlock.BlockNumberY; var blockContext = new ModContext <IWorldspaceBlockGetter>( modKey: modKey, parent: parent, record: readOnlyBlock); foreach (var readOnlySubBlock in readOnlyBlock.Items) { var subBlockNumY = readOnlySubBlock.BlockNumberY; var subBlockNumX = readOnlySubBlock.BlockNumberX; var subBlockContext = new ModContext <IWorldspaceSubBlockGetter>( modKey: modKey, parent: blockContext, record: readOnlySubBlock); foreach (var readOnlyCell in readOnlySubBlock.Items) { Func <IFallout4Mod, ICellGetter, bool, string?, ICell> cellGetter = (mod, copyCell, dup, edid) => { var worldspaceCopy = getOrAddAsOverride(mod, worldspace); var formKey = copyCell.FormKey; var retrievedBlock = worldspaceCopy.SubCells.FirstOrDefault(x => x.BlockNumberX == blockNumX && x.BlockNumberY == blockNumY); if (retrievedBlock == null) { retrievedBlock = new WorldspaceBlock() { BlockNumberX = blockNumX, BlockNumberY = blockNumY, GroupType = GroupTypeEnum.ExteriorCellBlock, }; worldspaceCopy.SubCells.Add(retrievedBlock); } var subBlock = retrievedBlock.Items.FirstOrDefault(x => x.BlockNumberX == subBlockNumX && x.BlockNumberY == subBlockNumY); if (subBlock == null) { subBlock = new WorldspaceSubBlock() { BlockNumberX = subBlockNumX, BlockNumberY = subBlockNumY, GroupType = GroupTypeEnum.ExteriorCellSubBlock, }; retrievedBlock.Items.Add(subBlock); } var cell = subBlock.Items.FirstOrDefault(cell => cell.FormKey == formKey); if (cell == null) { if (dup) { cell = copyCell.Duplicate(mod.GetNextFormKey(edid), CellCopyMask); } else { cell = copyCell.DeepCopy(CellCopyMask); } subBlock.Items.Add(cell); } return(cell); }; if (LoquiRegistration.TryGetRegister(type, out var regis) && regis.ClassType == typeof(Cell)) { yield return(new ModContext <IFallout4Mod, IMajorRecordCommon, IMajorRecordCommonGetter>( modKey: modKey, record: readOnlyCell, getOrAddAsOverride: (m, r) => cellGetter(m, (ICellGetter)r, false, default(string?)), duplicateInto: (m, r, e) => cellGetter(m, (ICellGetter)r, true, e), parent: subBlockContext)); } else { foreach (var con in CellCommon.Instance.EnumerateMajorRecordContexts( readOnlyCell, linkCache, type, modKey, subBlockContext, throwIfUnknown, (m, c) => cellGetter(m, c, false, default(string?)), (m, c, e) => cellGetter(m, c, true, e))) { yield return(con); } } } } } }
public static SettingsNodeVM MemberFactory(SettingsParameters param, string memberName, Type targetType, object?defaultVal) { switch (targetType.Name) { case "Boolean": return(new BoolSettingsVM(memberName, defaultVal)); case "SByte": return(new Int8SettingsVM(memberName, defaultVal)); case "Int16": return(new Int16SettingsVM(memberName, defaultVal)); case "Int32": return(new Int32SettingsVM(memberName, defaultVal)); case "Int64": return(new Int64SettingsVM(memberName, defaultVal)); case "Byte": return(new UInt8SettingsVM(memberName, defaultVal)); case "UInt16": return(new UInt16SettingsVM(memberName, defaultVal)); case "UInt32": return(new UInt32SettingsVM(memberName, defaultVal)); case "UInt64": return(new UInt64SettingsVM(memberName, defaultVal)); case "Double": return(new DoubleSettingsVM(memberName, defaultVal)); case "Single": return(new FloatSettingsVM(memberName, defaultVal)); case "Decimal": return(new DecimalSettingsVM(memberName, defaultVal)); case "ModKey": return(new ModKeySettingsVM(param.DetectedLoadOrder.Transform(x => x.Listing.ModKey), memberName, defaultVal)); case "FormKey": return(new FormKeySettingsVM(memberName, defaultVal)); case "Array`1": case "List`1": case "IEnumerable`1": { var firstGen = targetType.GenericTypeArguments[0]; switch (firstGen.Name) { case "SByte": return(EnumerableNumericSettingsVM.Factory <sbyte, Int8SettingsVM>(memberName, defaultVal, new Int8SettingsVM())); case "Int16": return(EnumerableNumericSettingsVM.Factory <short, Int16SettingsVM>(memberName, defaultVal, new Int16SettingsVM())); case "Int32": return(EnumerableNumericSettingsVM.Factory <int, Int32SettingsVM>(memberName, defaultVal, new Int32SettingsVM())); case "Int64": return(EnumerableNumericSettingsVM.Factory <long, Int64SettingsVM>(memberName, defaultVal, new Int64SettingsVM())); case "Byte": return(EnumerableNumericSettingsVM.Factory <byte, UInt8SettingsVM>(memberName, defaultVal, new UInt8SettingsVM())); case "UInt16": return(EnumerableNumericSettingsVM.Factory <ushort, UInt16SettingsVM>(memberName, defaultVal, new UInt16SettingsVM())); case "UInt32": return(EnumerableNumericSettingsVM.Factory <uint, UInt32SettingsVM>(memberName, defaultVal, new UInt32SettingsVM())); case "UInt64": return(EnumerableNumericSettingsVM.Factory <ulong, UInt64SettingsVM>(memberName, defaultVal, new UInt64SettingsVM())); case "Double": return(EnumerableNumericSettingsVM.Factory <double, DoubleSettingsVM>(memberName, defaultVal, new DoubleSettingsVM())); case "Single": return(EnumerableNumericSettingsVM.Factory <float, FloatSettingsVM>(memberName, defaultVal, new FloatSettingsVM())); case "Decimal": return(EnumerableNumericSettingsVM.Factory <decimal, DecimalSettingsVM>(memberName, defaultVal, new DecimalSettingsVM())); case "ModKey": return(EnumerableModKeySettingsVM.Factory(param, memberName, defaultVal)); case "FormKey": return(EnumerableFormKeySettingsVM.Factory(memberName, defaultVal)); default: { if (firstGen.Name.Contains("FormLink") && firstGen.IsGenericType && firstGen.GenericTypeArguments.Length == 1) { var formLinkGen = firstGen.GenericTypeArguments[0]; if (!LoquiRegistration.TryGetRegister(formLinkGen, out var regis)) { throw new ArgumentException($"Can't create a formlink control for type: {formLinkGen}"); } return(EnumerableFormLinkSettingsVM.Factory(param, memberName, regis.GetterType, defaultVal)); } var foundType = param.Assembly.GetType(firstGen.FullName !); if (foundType != null) { return(new EnumerableObjectSettingsVM(param, memberName, foundType)); } } return(new UnknownSettingsVM(memberName)); } } case "HashSet`1": { var firstGen = targetType.GenericTypeArguments[0]; switch (firstGen.Name) { case "ModKey": return(EnumerableModKeySettingsVM.Factory(param, memberName, defaultVal)); case "FormKey": return(EnumerableFormKeySettingsVM.Factory(memberName, defaultVal)); default: { if (firstGen.Name.Contains("FormLink") && firstGen.IsGenericType && firstGen.GenericTypeArguments.Length == 1) { var formLinkGen = firstGen.GenericTypeArguments[0]; if (!LoquiRegistration.TryGetRegister(formLinkGen, out var regis)) { throw new ArgumentException($"Can't create a formlink control for type: {formLinkGen}"); } return(EnumerableFormLinkSettingsVM.Factory(param, memberName, regis.GetterType, defaultVal)); } var foundType = param.Assembly.GetType(firstGen.FullName !); if (foundType != null) { return(new EnumerableObjectSettingsVM(param, memberName, foundType)); } } return(new UnknownSettingsVM(memberName)); } } default: { if (targetType.Name.Contains("FormLink") && targetType.IsGenericType && targetType.GenericTypeArguments.Length == 1) { return(new FormLinkSettingsVM(param.LinkCache, memberName, targetType)); } var foundType = param.Assembly.GetType(targetType.FullName !); if (foundType != null) { return(new ObjectSettingsVM(param, memberName, foundType)); } } return(new UnknownSettingsVM(memberName)); } }
internal static IEnumerable <IModContext <IOblivionMod, IMajorRecordCommon, IMajorRecordCommonGetter> > EnumerateMajorRecordContexts( this IReadOnlyList <IWorldspaceBlockGetter> worldspaceBlocks, IWorldspaceGetter worldspace, ILinkCache linkCache, Type type, ModKey modKey, IModContext?parent, bool throwIfUnknown, Func <IOblivionMod, IWorldspaceGetter, IWorldspace> getter) { foreach (var readOnlyBlock in worldspaceBlocks) { var blockNumX = readOnlyBlock.BlockNumberX; var blockNumY = readOnlyBlock.BlockNumberY; var blockModified = readOnlyBlock.LastModified; var blockContext = new ModContext <IWorldspaceBlockGetter>( modKey: modKey, parent: parent, record: readOnlyBlock); foreach (var readOnlySubBlock in readOnlyBlock.Items) { var subBlockNumY = readOnlySubBlock.BlockNumberY; var subBlockNumX = readOnlySubBlock.BlockNumberX; var subBlockModified = readOnlySubBlock.LastModified; var subBlockContext = new ModContext <IWorldspaceSubBlockGetter>( modKey: modKey, parent: blockContext, record: readOnlySubBlock); foreach (var readOnlyCell in readOnlySubBlock.Items) { Func <IOblivionMod, ICellGetter, ICell> cellGetter = (mod, copyCell) => { var worldspaceCopy = getter(mod, worldspace); var formKey = copyCell.FormKey; var retrievedBlock = worldspaceCopy.SubCells.FirstOrDefault(x => x.BlockNumberX == blockNumX && x.BlockNumberY == blockNumY); if (retrievedBlock == null) { retrievedBlock = new WorldspaceBlock() { BlockNumberX = blockNumX, BlockNumberY = blockNumY, GroupType = GroupTypeEnum.ExteriorCellBlock, LastModified = blockModified, }; worldspaceCopy.SubCells.Add(retrievedBlock); } var subBlock = retrievedBlock.Items.FirstOrDefault(x => x.BlockNumberX == subBlockNumX && x.BlockNumberY == subBlockNumY); if (subBlock == null) { subBlock = new WorldspaceSubBlock() { BlockNumberX = subBlockNumX, BlockNumberY = subBlockNumY, GroupType = GroupTypeEnum.ExteriorCellSubBlock, LastModified = readOnlySubBlock.LastModified, }; retrievedBlock.Items.Add(subBlock); } var cell = subBlock.Items.FirstOrDefault(cell => cell.FormKey == formKey); if (cell == null) { cell = copyCell.DeepCopy(CellCopyMask); subBlock.Items.Add(cell); } return(cell); }; if (LoquiRegistration.TryGetRegister(type, out var regis) && regis.ClassType == typeof(Cell)) { yield return(new ModContext <IOblivionMod, IMajorRecordCommon, IMajorRecordCommonGetter>( modKey: modKey, record: readOnlyCell, getter: (m, r) => cellGetter(m, (ICellGetter)r), parent: subBlockContext)); } else { foreach (var con in CellCommon.Instance.EnumerateMajorRecordContexts(readOnlyCell, linkCache, type, modKey, subBlockContext, throwIfUnknown, cellGetter)) { yield return(con); } } } } } }
internal static IEnumerable <IModContext <ISkyrimMod, IMajorRecordCommon, IMajorRecordCommonGetter> > EnumerateMajorRecordContexts( this IListGroupGetter <ICellBlockGetter> cellBlocks, ILinkCache linkCache, Type type, ModKey modKey, IModContext?parent, bool throwIfUnknown) { foreach (var readOnlyBlock in cellBlocks.Records) { var blockNum = readOnlyBlock.BlockNumber; var blockContext = new ModContext <ICellBlockGetter>( modKey: modKey, parent: parent, record: readOnlyBlock); foreach (var readOnlySubBlock in readOnlyBlock.SubBlocks) { var subBlockNum = readOnlySubBlock.BlockNumber; var subBlockContext = new ModContext <ICellSubBlockGetter>( modKey: modKey, parent: blockContext, record: readOnlySubBlock); foreach (var readOnlyCell in readOnlySubBlock.Cells) { Func <ISkyrimMod, ICellGetter, ICell> cellGetter = (mod, copyCell) => { var formKey = copyCell.FormKey; var retrievedBlock = mod.Cells.Records.FirstOrDefault(x => x.BlockNumber == blockNum); if (retrievedBlock == null) { retrievedBlock = new CellBlock() { BlockNumber = blockNum, GroupType = GroupTypeEnum.InteriorCellBlock, }; mod.Cells.Records.Add(retrievedBlock); } var subBlock = retrievedBlock.SubBlocks.FirstOrDefault(x => x.BlockNumber == subBlockNum); if (subBlock == null) { subBlock = new CellSubBlock() { BlockNumber = subBlockNum, GroupType = GroupTypeEnum.InteriorCellSubBlock, }; retrievedBlock.SubBlocks.Add(subBlock); } var cell = subBlock.Cells.FirstOrDefault(cell => cell.FormKey == formKey); if (cell == null) { cell = copyCell.DeepCopy(CellCopyMask); subBlock.Cells.Add(cell); } return(cell); }; if (LoquiRegistration.TryGetRegister(type, out var regis) && regis.ClassType == typeof(Cell)) { yield return(new ModContext <ISkyrimMod, IMajorRecordCommon, IMajorRecordCommonGetter>( modKey: modKey, record: readOnlyCell, getter: (m, r) => cellGetter(m, (ICellGetter)r), parent: subBlockContext)); } else { foreach (var con in CellCommon.Instance.EnumerateMajorRecordContexts(readOnlyCell, linkCache, type, modKey, subBlockContext, throwIfUnknown, cellGetter)) { yield return(con); } } } } } }