Глобальный рефакторинг пространств имён

This commit is contained in:
2025-10-02 13:29:30 +04:00
parent d23d81fb53
commit 2fa94851cb
3176 changed files with 27146 additions and 30584 deletions
@@ -0,0 +1,67 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Compendium;
/// <summary>
/// Загрузчик данных компендиума.
/// </summary>
/// <param name="repository"><inheritdoc cref="FoundryEnRepository"/></param>
internal sealed class FoundryEnCompendium(FoundryEnRepository repository) : AbstractCompendium
{
/// <inheritdoc/>
public override FoundryEnRepository Repository { get; } = repository;
/// <summary>
/// Коллекция всех записей компендиума.
/// </summary>
public ConcurrentBag<FoundryEnCompendiumItem> Items { get; } = [];
/// <inheritdoc/>
public override int Count(params ICollection<string> types) =>
types.Count == 0 ? Items.Count : Items.Count(i => types.Contains(i.Type));
/// <inheritdoc/>
public override IEnumerable<Tuple<AbstractCompendiumItem, JObject>> Iterate(
params ICollection<string> types
)
{
IEnumerable<string> files =
types.Count == 0
? Items.Select(item => item.File).Distinct()
: Items
.Where(item => types.Contains(item.Type))
.Select(item => item.File)
.Distinct();
foreach (string file in files)
{
Dictionary<string, FoundryEnCompendiumItem> fileReferences = Items
.Where(i => i.File == file)
.ToDictionary(i => i.Id);
using StreamReader fileReader = new(file);
JArray array = JArray.Parse(fileReader.ReadToEnd());
foreach (JToken item in array)
{
string? id = item.SelectToken("_id")?.ToString();
if (
id is null
|| !fileReferences.TryGetValue(id, out FoundryEnCompendiumItem? reference)
|| (types.Count > 0 && !types.Contains(reference.Type))
)
{
continue;
}
yield return new(reference, (JObject)item);
}
}
}
}
@@ -0,0 +1,25 @@
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Compendium;
/// <summary>
/// Ссылка на сущность с указанием файла, в котором она хранится.
/// </summary>
/// <param name="id">Идентификатор сущности.</param>
/// <param name="type">Тип сущности.</param>
/// <param name="file">Имя файла, в котором хранится сущность.</param>
internal class FoundryEnCompendiumItem(string id, string type, string file) : AbstractCompendiumItem
{
/// <summary>
/// Идентификатор сущности.
/// </summary>
public override string Id { get; } = id;
/// <summary>
/// Тип сущности.
/// </summary>
public override string Type { get; } = type;
/// <summary>
/// Имя файла, в котором хранится сущность.
/// </summary>
public string File { get; } = file;
}
@@ -0,0 +1,54 @@
using Microsoft.Extensions.DependencyInjection;
using Pf2e.Scrapper.Importers.Implementations.FoundryEn.Compendium;
using Pf2e.Scrapper.Importers.Implementations.FoundryEn.Helpers;
using Pf2e.Scrapper.Importers.Repositories;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn;
/// <summary>
/// Импортёр для модуля Pf2e FoundryVTT.
/// </summary>
internal class FoundryEnImporter : AbstractImporter
{
/// <summary>
/// Название внешней ссылки.
/// </summary>
public const string TargetName = "Pf2e FoundryVTT module";
/// <summary>
/// Отображаемое имя импортёра.
/// </summary>
public override string Name => TargetName;
/// <summary>
/// Короткое имя импортёра.
/// </summary>
public override string Slug => "foundry-en";
#region "Внедрение зависимостей"
public static void RegisterServices(IServiceCollection services)
{
services.AddSingleton<FoundryEnImporter>();
services.AddSingleton<FoundryEnRepository>();
services.AddSingleton<FoundryEnCompendium>();
// Помощники
services.AddSingleton<FoundryEnGlobals>();
}
#endregion
}
/// <summary>
/// Git-репозиторий данных FoundryVTT-модуля "pf2e".
/// </summary>
/// <param name="importer"><inheritdoc cref="FoundryEnImporter"/></param>
internal class FoundryEnRepository(FoundryEnImporter importer) : AbstractGitHubRepository(importer)
{
/// <inheritdoc/>
public override string Repository => "foundryvtt/pf2e";
/// <inheritdoc/>
public override string AssetName => "json-assets.zip";
}
@@ -0,0 +1,76 @@
using System.Collections.Generic;
using System.IO;
using AngleSharp.Dom;
using Newtonsoft.Json.Linq;
using Pf2e.Database.Model.Base.Targets;
using Pf2e.Database.Model.Structure;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Helpers;
/// <summary>
/// Глобальные константы и утилиты для импорта данных в формате Foundry En.
/// </summary>
internal class FoundryEnGlobals
{
/// <summary>
/// Цель внешних ссылок для Foundry En.
/// </summary>
public ExternalTarget FoundryTarget { get; set; } = null!;
/// <summary>
/// Список идентификаторв пропускаемых сущностей.
/// </summary>
public List<string> Ignore { get; } = [];
/// <summary>
/// Словарей суффиксов для сущностей.
/// </summary>
public Dictionary<string, string> SlugSuffixes { get; } = [];
/// <summary>
/// Словарь соответствий идентификаторов Aonprd к Foundry En.
/// </summary>
public Dictionary<string, string> MatchToAonprd { get; } = [];
/// <summary>
/// Конструктор класса <see cref="FoundryEnGlobals"/>.
/// </summary>
public FoundryEnGlobals()
{
using StreamReader fileReader = new("Resources\\ImportAdaptation.json");
JObject? json = JObject
.Parse(fileReader.ReadToEnd())
.SelectToken("Foundry")
?.ToObject<JObject>();
if (json is not null)
{
Ignore = json.SelectToken("Ignore")?.ToObject<List<string>>() ?? []; // JsonToDictionary(json, "Ignore");
SlugSuffixes = JsonToDictionary(json, "SlugSuffixes");
MatchToAonprd = JsonToDictionary(json, "MatchToAonprd");
}
}
/// <summary>
/// Получить суффикс для ссылки.
/// </summary>
/// <param name="id">Идентификатор Aonprd.</param>
/// <returns>Суффикс для ссылки или пустая строка.</returns>
public string GetSlugSuffix(string id)
{
return SlugSuffixes.TryGetValue(id, out string? slug) ? $"-{slug}" : string.Empty;
}
/// <summary>
/// Преобразовать JSON-объект в словарь.
/// </summary>
/// <param name="json">Исходный JSON-объект.</param>
/// <param name="tokenPath">Путь к токену в JSON.</param>
/// <returns>Результирующий словарь.</returns>
public static Dictionary<string, string> JsonToDictionary(JObject json, string tokenPath)
{
return json.SelectToken(tokenPath)?.ToObject<Dictionary<string, string>>() ?? [];
}
}
@@ -0,0 +1,43 @@
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;
using Pf2e.Scrapper.Helpers;
using Pf2e.Scrapper.Importers.Implementations.FoundryEn.Helpers;
using Pf2e.Scrapper.Processors;
using Pf2e.Scrapper.Processors.Attributes;
using Pf2e.Database;
using Pf2e.Database.Model.Common.I18n;
using Pf2e.Database.Model.Enum;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Processors.Entities;
[ProcessorCollection(
"foundry-en:action",
InnerType = "action",
CompendiumType = ProcessorCompendiumEnum.FoundryEn,
Description = "Действия",
Group = ProcessorGroupEnum.FoundryEnEntities,
Active = false
)]
[ProcessorDependencies(["foundry-en:compendium", "foundry-en:external"])]
internal partial class ActionProcessor(
DatabaseHelper databaseHelper,
Pf2eDbContext context,
FoundryEnGlobals globals,
ProcessorInput input
)
: FoundryEnAbstractProcessor<Database.Model.Structure.Action>(
databaseHelper,
context,
globals,
input
)
{
public override EntityType Type => EntityType.Action;
public override void Process()
{
base.Process();
}
}
@@ -0,0 +1,49 @@
using Newtonsoft.Json.Linq;
using Pf2e.Scrapper.Helpers;
using Pf2e.Scrapper.Importers.Implementations.FoundryEn.Helpers;
using Pf2e.Scrapper.Processors;
using Pf2e.Scrapper.Processors.Attributes;
using Pf2e.Scrapper.Processors.Collection;
using Pf2e.Database;
using Pf2e.Database.Model.Enum;
using Pf2e.Database.Model.Structure;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Processors.Entities;
[ProcessorCollection(
"foundry-en:condition",
InnerType = "Item.condition",
CompendiumType = ProcessorCompendiumEnum.FoundryEn,
Description = "Состояния",
Group = ProcessorGroupEnum.FoundryEnEntities,
Active = false
)]
[ProcessorDependencies(["foundry-en:compendium"])]
internal class ConditionProcessor(
DatabaseHelper databaseHelper,
Pf2eDbContext context,
FoundryEnGlobals globals,
ProcessorInput input
) : FoundryEnAbstractProcessor<Condition>(databaseHelper, context, globals, input)
{
public override EntityType Type => EntityType.Condition;
public override void Process()
{
base.Process();
/*
JObject extra = new()
{
{ "duration", Input.Input.SelectToken("system.duration") },
{ "overrides", Input.Input.SelectToken("system.overrides") },
{ "references", Input.Input.SelectToken("system.references") },
{ "value", Input.Input.SelectToken("system.value") },
};
Object.Extra = extra.ToString(Newtonsoft.Json.Formatting.None);
Object.Group = Input.EnumOptional("system.group", ConditionGroup.Unknown);
Context.Conditions.Add(Object);
*/
}
}
@@ -0,0 +1,89 @@
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using Pf2e.Scrapper.Helpers;
using Pf2e.Scrapper.Importers.Implementations.FoundryEn.Helpers;
using Pf2e.Scrapper.Processors;
using Pf2e.Scrapper.Processors.Attributes;
using Pf2e.Database;
using Pf2e.Database.Model.Enum;
using Pf2e.Database.Model.Structure;
using Pf2e.Database.Model.Structure.DeityRelation;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Processors.Entities;
[ProcessorCollection(
"foundry-en:deity",
InnerType = "deity",
CompendiumType = ProcessorCompendiumEnum.FoundryEn,
Description = "Божества",
Group = ProcessorGroupEnum.FoundryEnEntities,
Active = true
)]
[ProcessorDependencies(["foundry-en:compendium", "foundry-en:external"])]
internal class DeityProcessor(
DatabaseHelper databaseHelper,
Pf2eDbContext context,
FoundryEnGlobals globals,
ProcessorInput input
) : FoundryEnAbstractProcessor<Deity>(databaseHelper, context, globals, input)
{
public override EntityType Type => EntityType.Deity;
public override void Process()
{
base.Process();
ProcessSanctification();
ProcessWeapons();
}
private void ProcessSanctification()
{
JObject? sanctification = Input.GetOptional<JObject>("system.sanctification");
if (sanctification == null)
{
Object.Sanctification = DeitySanctification.Any;
Object.SanctificationMust = false;
return;
}
if (
sanctification["what"] is not JArray sanctificationArray
|| sanctificationArray.Count == 0
|| sanctificationArray.Count == 2
&& sanctificationArray.Any(t => t.ToString() == "holy")
&& sanctificationArray.Any(t => t.ToString() == "unholy")
)
{
Object.Sanctification = DeitySanctification.Any;
}
else if (sanctificationArray.Any(t => t.ToString() == "holy"))
{
Object.Sanctification = DeitySanctification.Holy;
}
else if (sanctificationArray.Any(t => t.ToString() == "unholy"))
{
Object.Sanctification = DeitySanctification.Unholy;
}
else
{
Object.Sanctification = DeitySanctification.Any;
}
Object.SanctificationMust = sanctification["modal"]?.ToString() == "must";
}
private void ProcessWeapons()
{
List<string> weapons = Input
.GetRequired<JArray>("system.weapons")
.Select(token => token.ToString())
.ToList();
foreach (string weapon in weapons)
{
Object.DeityWeapons.Add(new() { DeityId = Object.Id, Weapon = weapon });
}
}
}
@@ -0,0 +1,201 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
using Pf2e.Scrapper.Helpers;
using Pf2e.Scrapper.Importers.Implementations.FoundryEn.Helpers;
using Pf2e.Scrapper.Processors;
using Pf2e.Scrapper.Processors.Attributes;
using Pf2e.Scrapper.Processors.Definitions;
using Pf2e.Database;
using Pf2e.Database.Model;
using Pf2e.Database.Model.Base;
using Pf2e.Database.Model.Base.Targets;
using Pf2e.Database.Model.Common.I18n;
using Pf2e.Database.Model.Enum;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Processors;
/// <summary>
/// Абстрактный класс-обработчик сущностей, полученных из молуля Foundry pf2e.
/// Класс предназначен для обработки данных с помощью различных обработчиков,
/// для которых указан атрибут <see cref="ProcessorAttribute"/>.
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="databaseHelper">[DI] <inheritdoc cref="DatabaseHelper"/></param>
/// <param name="context">[DI] <inheritdoc cref="Pf2eDbContext"/></param>
/// <param name="globals">[DI] <inheritdoc cref="FoundryEnGlobals"/></param>
/// <param name="input">Объект обработки вводимого JSON.</param>
internal abstract class FoundryEnAbstractProcessor<TEntity>(
DatabaseHelper databaseHelper,
Pf2eDbContext context,
FoundryEnGlobals globals,
ProcessorInput input
) : AbstractInputProcessor(input)
where TEntity : class, IEntity
{
/// <inheritdoc cref="DatabaseHelper"/>
protected DatabaseHelper Helper { get; } = databaseHelper;
/// <inheritdoc cref="Pf2eDbContext"/>
public Pf2eDbContext Context { get; } = context;
/// <inheritdoc cref="FoundryEnGlobals"/>
public FoundryEnGlobals Globals { get; } = globals;
/// <summary>
/// Тип сущности.
/// </summary>
public abstract EntityType Type { get; }
/// <summary>
/// Представление сущности, которое будет использоваться для обработки данных.
/// </summary>
public EntityView View { get; private set; } = null!;
/// <summary>
/// Основная сущность, которая будет использоваться для обработки данных.
/// </summary>
public Entity Entity => View.Entity;
/// <summary>
/// Подчинённая сущность, которая будет использоваться для обработки данных.
/// </summary>
public TEntity Object =>
View.SubEntity as TEntity
?? throw new InvalidOperationException(
$"Сущность {View.SubEntity} некорректного типа, ожидался тип {typeof(TEntity)}."
);
/// <summary>
/// Название сущности, которое будет использоваться для обработки данных.
/// </summary>
public string Name
{
get { return _name ??= GetEntityName(); }
}
private string? _name = null;
/// <summary>
/// Проверяет входные данные на наличие идентификатора сущности и игнорирует её, если она указана в списке игнорируемых.
/// </summary>
public virtual void CheckEntity()
{
string id = Input.GetRequired<string>("_id");
if (Globals.Ignore.Any(s => s == id))
{
throw new SkipItemException(
id,
$"Сущность с идентификатором \"{id}\" пропущена, так как она указана в списке игнорируемых."
);
}
}
/// <summary>
/// Разрешает сущность, основываясь на входных данных.
/// </summary>
/// <returns>Идентификатор сущности.</returns>
public virtual int ResolveEntity()
{
string name = Name;
if (Globals.MatchToAonprd.TryGetValue(name, out string? aonprdId))
{
return Context
.EntityExternals.Where(ex => ex.ExternalId == aonprdId)
.Select(ex => ex.EntityId)
.First();
}
try
{
List<Entity> entities = Context
.Entities.AsNoTracking()
.Include(e => e.Traits)
.ThenInclude(t => t.Entity)
.Where(e => Pf2eDbContext.LocaleSearch(e.Name, name) && e.Type == Type)
.ToList();
switch (entities.Count)
{
case 0:
throw new("сущность не найдена.");
case 1:
return entities[0].Id;
}
JArray? traitArray = Input.GetOptional<JArray>("system.traits.value");
if (traitArray is not null)
{
List<string> inputTraits = traitArray
.Select(token => token.ToString())
.Order()
.ToList();
foreach (Entity entity in entities)
{
List<string> entityTraits = entity
.Traits.Select(t => t.Entity.Name[LocaleType.English])
.Order()
.ToList();
if (entityTraits.SequenceEqual(inputTraits))
{
return entity.Id;
}
}
}
}
catch (Exception ex)
{
throw new SkipItemException(name, ex.Message);
}
throw new SkipItemException(
name,
$"Несколько сущностей \"{name}\" найдено, но ни одна не совпадает с входными данными по признакам."
);
}
/// <inheritdoc/>
public override void Process()
{
CheckEntity();
View = new(Context, Type, ResolveEntity());
AddExternal();
}
/// <inheritdoc/>
public override void Save()
{
Context.SaveChanges();
}
/// <summary>
/// Получить имя сущности из входных данных.
/// </summary>
/// <returns>Имя сущности.</returns>
protected virtual string GetEntityName() => Input.GetRequired<string>("name");
/// <summary>
/// Генерация внешних ссылок сущности.
/// </summary>
protected virtual void AddExternal()
{
// External
EntityExternal external = new()
{
EntityId = Entity.Id,
TargetId = Globals.FoundryTarget.Id,
ExternalId = Input.GetOptional<string>("_id"),
Suffix = Input.GetRequired<string>("_id"),
Md5 = Input.Md5(),
};
Context.EntityExternals.Add(external);
}
}
@@ -0,0 +1,72 @@
using System;
using System.IO;
using System.Text;
using Newtonsoft.Json.Linq;
using Pf2e.Scrapper.Helpers;
using Pf2e.Scrapper.Importers.Implementations.FoundryEn.Compendium;
using Pf2e.Scrapper.Processors.Attributes;
using Pf2e.Scrapper.Processors.Definitions;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Processors.Preparation;
[Processor(
"foundry-en:compendium",
Description = "Загрузка компендиума",
Group = ProcessorGroupEnum.FoundryEnPreparation,
Active = false
)]
[ProcessorDependencies(["foundry-en:repository"])]
internal class CompendiumProcessor(
FoundryEnRepository repository,
FoundryEnCompendium compendium,
ProcessProgress progress
) : IProcessor
{
public FoundryEnRepository Repository { get; } = repository;
public FoundryEnCompendium Compendium { get; } = compendium;
public ProcessProgress Progress { get; } = progress;
public void Process()
{
string packsDir = Path.Combine(Repository.RepositoryDirPath, "packs");
var jsonFiles = Directory.GetFiles(packsDir, "*.json");
Progress.Local.Reset(jsonFiles.Length);
foreach (string packFile in jsonFiles)
{
Progress.Local.Start(Path.GetFileName(packFile));
if (packFile.EndsWith("folders.json", StringComparison.OrdinalIgnoreCase))
{
Progress.Local.End();
continue;
}
using StreamReader fileReader = new(packFile, Encoding.UTF8);
string fileContent = fileReader.ReadToEnd();
JArray packData = JArray.Parse(fileContent);
foreach (JToken item in packData)
{
string id = item.SelectToken("_id")?.ToString()!;
string? type = item.SelectToken("type")?.ToString();
if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(type))
{
continue;
}
FoundryEnCompendiumItem compendiumItem = new(id, type, packFile);
Compendium.Items.Add(compendiumItem);
}
Progress.Local.End();
}
Progress.Local.Complete();
}
public void Save() { }
}
@@ -0,0 +1,40 @@
using Pf2e.Scrapper.Importers.Implementations.FoundryEn.Helpers;
using Pf2e.Scrapper.Processors.Attributes;
using Pf2e.Scrapper.Processors.Definitions;
using Pf2e.Scrapper.Importers.Implementations.Aonprd.Helpers;
using Pf2e.Database;
using Pf2e.Database.Model.Base.Targets;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Processors.Preparation;
[Processor(
"foundry-en:external",
Description = "Создание цели внешних ссылок",
Group = ProcessorGroupEnum.FoundryEnPreparation
)]
[ProcessorDependencies(["foundry-en:repository"])]
internal class ExternalProcessor(FoundryEnGlobals enGlobals) : AbstractSimpleProcessor
{
public Pf2eDbContext Context { get; } = new();
public FoundryEnGlobals EnGlobals { get; } = enGlobals;
public ExternalTarget FoundryTarget = null!;
public override void Process()
{
FoundryTarget = new()
{
Name = FoundryEnImporter.TargetName,
Icon = "http://www.google.com/s2/favicons?domain=foundryvtt.com",
Prefix = "",
};
}
public override void Save()
{
Context.ExternalTargets.Add(FoundryTarget);
Context.SaveChanges();
EnGlobals.FoundryTarget = FoundryTarget;
}
}
@@ -0,0 +1,25 @@
using Pf2e.Scrapper.Helpers;
using Pf2e.Scrapper.Processors.Attributes;
using Pf2e.Scrapper.Processors.Definitions;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Processors.Preparation;
[Processor(
"foundry-en:repository",
Description = "Обновление репозитория",
Group = ProcessorGroupEnum.FoundryEnPreparation,
Active = false
)]
internal class RepositoryUpdateProcessor(FoundryEnRepository repository, ProcessProgress progress)
: IProcessor
{
public FoundryEnRepository Repository { get; } = repository;
public ProcessProgress Progress { get; } = progress;
public void Process()
{
Repository.Update(Progress);
}
public void Save() { }
}
@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Pf2e.Scrapper.Helpers;
using Pf2e.Scrapper.Importers.Implementations.FoundryEn.Compendium;
using Pf2e.Scrapper.Processors.Attributes;
using Pf2e.Scrapper.SchemaBuilder;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Processors.Preparation;
[Processor(
"foundry-en:schema",
Description = "Построение схемы данных",
Group = ProcessorGroupEnum.FoundryEnPreparation,
Active = false
)]
[ProcessorDependencies(["foundry-en:compendium"])]
internal class SchemaBuildProcessor(
FoundryEnImporter importer,
FoundryEnRepository repository,
FoundryEnCompendium compendium,
ProcessProgress progress,
ApplicationSettings settings
) : AbstractSchemaBuildProcessor
{
/// <inheritdoc cref="FoundryEnImporter"/>
protected FoundryEnImporter Importer { get; } = importer;
/// <inheritdoc cref="FoundryEnRepository"/>
protected FoundryEnRepository Repository { get; } = repository;
/// <inheritdoc cref="FoundryEnCompendium"/>
protected override FoundryEnCompendium Compendium { get; } = compendium;
/// <inheritdoc cref="ProcessProgress"/>
protected override ProcessProgress Progress { get; } = progress;
/// <inheritdoc cref="ApplicationSettings"/>
protected ApplicationSettings Settings { get; } = settings;
/// <inheritdoc/>
protected override string SavePath => Path.Combine(Settings.OutputDirPath, Importer.Slug);
/// <summary>
/// Определитель типов данных.
/// </summary>
protected override SchemaTypeResolver Resolver { get; } = new();
/// <summary>
/// Список типов, являющихся экипировкой.
/// </summary>
private readonly string[] _equipmentTypes =
[
"equipment",
"armor",
"backpack",
"consumable",
"kit",
"shield",
"treasure",
"weapon",
];
/// <inheritdoc/>
protected override ICollection<string> GetSchemaNodes(AbstractCompendiumItem item)
{
List<string> nodes = [item.Type];
// Нода подкласса
if (_equipmentTypes.Contains(item.Type))
{
nodes.Add("_equipment");
}
return nodes;
}
}
@@ -0,0 +1,55 @@
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Pf2e.Scrapper.SchemaBuilder;
using Pf2e.Scrapper.SchemaBuilder.Types;
namespace Pf2e.Scrapper.Importers.Implementations.FoundryEn.Processors.Preparation;
internal class SchemaTypeResolver : TypeResolver
{
public class FoundryRulesSchemaType(SchemaNode parent) : IgnoreSchemaType(parent)
{
public override string GetTypeName()
{
return "ignored (Foundry rules object)";
}
}
protected readonly List<string> DictionaryPaths =
[
"character.items.[].system.items",
"character.items.[].system.overlays",
"ancestry.system.items",
"ancestry.system.boosts",
"background.system.boosts",
"background.system.items",
"class.system.items",
"consumable.system.spell.system.damage",
"consumable.system.spell.system.overlays",
"deity.system.spells",
"feat.system.subfeatures.proficiencies",
"kit.system.items",
"kit.system.items.[value].items",
"spell.system.damage",
"spell.system.heightening.damage",
"spell.system.heightening.levels",
"spell.system.heightening.levels.[value].damage",
"spell.system.overlays",
"spell.system.overlays.[value].system.damage",
"spell.system.overlays.[value].system.heightening",
"spell.system.overlays.[value].system.heightening.[value]",
];
/// <summary>
/// Частное определение типа поля.
/// </summary>
/// <param name="node">Поле схемы данных, для которого создаётся тип.</param>
/// <param name="value">Добавляемое значение.</param>
/// <returns>Новый тип для схемы данных. `null`, что бы использовать значение по умолчанию</returns>
protected override AbstractSchemaType? CustomResolve(SchemaNode node, JToken? value)
{
return CheckPath(node, DictionaryPaths) ? new DictionarySchemaType(node)
: node.Path.EndsWith(".rules") ? new FoundryRulesSchemaType(node)
: (AbstractSchemaType?)null;
}
}