Move data and data loading to plugin libraries.
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Deukhoofd 2025-05-16 13:01:23 +02:00
parent b6ff51c9df
commit 810cdbb15a
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
46 changed files with 108405 additions and 155 deletions

View File

@ -7,17 +7,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="8.0.5" />
<PackageReference Include="System.Text.Json" Version="8.0.5"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PkmnLib.Static\PkmnLib.Static.csproj" />
<ProjectReference Include="..\PkmnLib.Static\PkmnLib.Static.csproj"/>
</ItemGroup>
<ItemGroup>
<Reference Include="JetBrains.Annotations">
<HintPath>..\..\..\..\.nuget\packages\jetbrains.annotations\2024.2.0\lib\netstandard2.0\JetBrains.Annotations.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -1,15 +1,12 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using PkmnLib.Dataloader.Models;
using PkmnLib.Dynamic.Libraries.DataLoaders.Models;
using PkmnLib.Static.Libraries;
using PkmnLib.Static.Species;
using PkmnLib.Static.Utils;
namespace PkmnLib.Dataloader;
namespace PkmnLib.Dynamic.Libraries.DataLoaders;
public static class AbilityDataLoader
{
@ -29,24 +26,14 @@ public static class AbilityDataLoader
return objects;
}
public static AbilityLibrary LoadAbilities(Stream[] streams)
{
var library = new AbilityLibrary();
var objects = streams.SelectMany(LoadAbilitiesData);
if (objects == null)
throw new InvalidDataException("Ability data is empty.");
var abilities = objects.Select(x => DeserializeAbility(x.Key, x.Value));
foreach (var a in abilities)
library.Add(a);
return library;
}
public static AbilityLibrary LoadAbilities(Stream stream)
public static AbilityLibrary LoadAbilities(Stream stream,
Action<Dictionary<string, SerializedAbility>>? action = null)
{
var library = new AbilityLibrary();
var objects = LoadAbilitiesData(stream);
if (objects == null)
throw new InvalidDataException("Ability data is empty.");
action?.Invoke(objects);
var abilities = objects.Select(x => DeserializeAbility(x.Key, x.Value));
foreach (var a in abilities)

View File

@ -1,10 +1,8 @@
using System.Collections.Generic;
using System.Linq;
using PkmnLib.Dataloader.Models;
using PkmnLib.Dynamic.Libraries.DataLoaders.Models;
using PkmnLib.Static.Moves;
using PkmnLib.Static.Utils;
namespace PkmnLib.Dataloader;
namespace PkmnLib.Dynamic.Libraries.DataLoaders;
internal static class CommonDataLoaderHelper
{

View File

@ -1,20 +1,20 @@
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using PkmnLib.Static;
using PkmnLib.Static.Libraries;
namespace PkmnLib.Dataloader;
namespace PkmnLib.Dynamic.Libraries.DataLoaders;
public static class GrowthRateDataLoader
{
public static GrowthRateLibrary LoadGrowthRates(Stream stream)
public static GrowthRateLibrary LoadGrowthRates(Stream stream, Action<List<IGrowthRate>>? action = null)
{
var objects = JsonSerializer.Deserialize<Dictionary<string, uint[]>>(stream, JsonOptions.DefaultOptions)!;
var growthRates = objects.Select(x => new LookupGrowthRate(x.Key, x.Value)).Cast<IGrowthRate>().ToList();
action?.Invoke(growthRates);
var library = new GrowthRateLibrary();
foreach (var (key, value) in objects)
foreach (var growthRate in growthRates)
{
var growthRate = new LookupGrowthRate(key, value);
library.Add(growthRate);
}
return library;

View File

@ -1,26 +1,23 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text.Json;
using JetBrains.Annotations;
using PkmnLib.Dataloader.Models;
using PkmnLib.Dynamic.Libraries.DataLoaders.Models;
using PkmnLib.Static;
using PkmnLib.Static.Libraries;
using PkmnLib.Static.Moves;
using PkmnLib.Static.Utils;
namespace PkmnLib.Dataloader;
namespace PkmnLib.Dynamic.Libraries.DataLoaders;
public static class ItemDataLoader
{
public static ItemLibrary LoadItems(Stream stream)
public static ItemLibrary LoadItems(Stream stream, Action<List<SerializedItem>>? onAfterLoad = null)
{
var library = new ItemLibrary();
var obj = JsonSerializer.Deserialize<SerializedItem[]>(stream, JsonOptions.DefaultOptions);
var obj = JsonSerializer.Deserialize<List<SerializedItem>>(stream, JsonOptions.DefaultOptions);
if (obj == null)
throw new InvalidDataException("Item data is empty.");
onAfterLoad?.Invoke(obj);
var items = obj.Select(DeserializeItem);
foreach (var i in items)
library.Add(i);

View File

@ -1,6 +1,6 @@
using System.Text.Json;
namespace PkmnLib.Dataloader;
namespace PkmnLib.Dynamic.Libraries.DataLoaders;
internal static class JsonOptions
{

View File

@ -1,10 +1,8 @@
using System;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using PkmnLib.Static.Utils;
namespace PkmnLib.Dataloader;
namespace PkmnLib.Dynamic.Libraries.DataLoaders;
internal static class JsonParameterLoader
{

View File

@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Text.Json.Nodes;
namespace PkmnLib.Dataloader.Models;
namespace PkmnLib.Dynamic.Libraries.DataLoaders.Models;
public class SerializedAbility
{

View File

@ -1,9 +1,8 @@
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace PkmnLib.Dataloader.Models;
namespace PkmnLib.Dynamic.Libraries.DataLoaders.Models;
public class SerializedItem
{

View File

@ -1,9 +1,8 @@
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace PkmnLib.Dataloader.Models;
namespace PkmnLib.Dynamic.Libraries.DataLoaders.Models;
public class SerializedMoveDataWrapper
{

View File

@ -1,9 +1,8 @@
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace PkmnLib.Dataloader.Models;
namespace PkmnLib.Dynamic.Libraries.DataLoaders.Models;
public class SerializedSpecies
{

View File

@ -1,26 +1,24 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text.Json;
using JetBrains.Annotations;
using PkmnLib.Dataloader.Models;
using PkmnLib.Dynamic.Libraries.DataLoaders.Models;
using PkmnLib.Static;
using PkmnLib.Static.Libraries;
using PkmnLib.Static.Moves;
using PkmnLib.Static.Utils;
namespace PkmnLib.Dataloader;
namespace PkmnLib.Dynamic.Libraries.DataLoaders;
public static class MoveDataLoader
{
public static MoveLibrary LoadMoves(Stream stream, TypeLibrary typeLibrary)
public static MoveLibrary LoadMoves(Stream stream, TypeLibrary typeLibrary,
Action<SerializedMoveDataWrapper>? onAfterLoad = null)
{
var library = new MoveLibrary();
var objects = JsonSerializer.Deserialize<SerializedMoveDataWrapper>(stream, JsonOptions.DefaultOptions);
if (objects == null)
throw new InvalidDataException("Move data is empty.");
onAfterLoad?.Invoke(objects);
var moves = objects.Data.Select(x => DeserializeMove(x, typeLibrary));
foreach (var m in moves)
library.Add(m);

View File

@ -1,10 +1,7 @@
using System;
using System.IO;
using System.Linq;
using PkmnLib.Static;
using PkmnLib.Static.Libraries;
namespace PkmnLib.Dataloader;
namespace PkmnLib.Dynamic.Libraries.DataLoaders;
public static class NatureDataLoader
{

View File

@ -1,17 +1,13 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using PkmnLib.Dataloader.Models;
using PkmnLib.Dynamic.Libraries.DataLoaders.Models;
using PkmnLib.Static;
using PkmnLib.Static.Libraries;
using PkmnLib.Static.Species;
using PkmnLib.Static.Utils;
namespace PkmnLib.Dataloader;
namespace PkmnLib.Dynamic.Libraries.DataLoaders;
public static class SpeciesDataLoader
{
@ -24,24 +20,14 @@ public static class SpeciesDataLoader
x => x.Value.Deserialize<SerializedSpecies>(JsonOptions.DefaultOptions))!;
}
public static SpeciesLibrary LoadSpecies(Stream[] streams, IReadOnlyTypeLibrary typeLibrary)
{
var library = new SpeciesLibrary();
var objects = streams.SelectMany(LoadSpeciesData);
if (objects == null)
throw new InvalidDataException("Species data is empty.");
var species = objects.Select(x => DeserializeSpecies(x.Value, typeLibrary));
foreach (var s in species)
library.Add(s);
return library;
}
public static SpeciesLibrary LoadSpecies(Stream stream, IReadOnlyTypeLibrary typeLibrary)
public static SpeciesLibrary LoadSpecies(Stream stream, IReadOnlyTypeLibrary typeLibrary,
Action<Dictionary<string, SerializedSpecies>>? action = null)
{
var library = new SpeciesLibrary();
var objects = LoadSpeciesData(stream);
if (objects == null)
throw new InvalidDataException("Species data is empty.");
action?.Invoke(objects);
var species = objects.Select(x => DeserializeSpecies(x.Value, typeLibrary));
foreach (var s in species)
library.Add(s);

View File

@ -1,9 +1,6 @@
using System;
using System.IO;
using System.Linq;
using PkmnLib.Static.Libraries;
namespace PkmnLib.Dataloader;
namespace PkmnLib.Dynamic.Libraries.DataLoaders;
public static class TypeDataLoader
{

View File

@ -50,24 +50,12 @@ public class DynamicLibraryImpl : IDynamicLibrary
/// Initializes a new instance of the <see cref="DynamicLibraryImpl"/> class, with the given
/// plugins and static library.
/// </summary>
public static IDynamicLibrary Create(IStaticLibrary staticLibrary, IEnumerable<Plugin> plugins)
public static IDynamicLibrary Create(IEnumerable<Plugin> plugins)
{
var registry = new ScriptRegistry();
foreach (var plugin in plugins.OrderBy(x => x.LoadOrder))
{
plugin.Register(registry);
}
if (registry.DamageCalculator is null)
throw new InvalidOperationException("Damage calculator not found in plugins.");
if (registry.BattleStatCalculator is null)
throw new InvalidOperationException("Stat calculator not found in plugins.");
if (registry.MiscLibrary is null)
throw new InvalidOperationException("Misc library not found in plugins.");
if (registry.CaptureLibrary is null)
throw new InvalidOperationException("Capture library not found in plugins.");
var scriptResolver = new ScriptResolver(registry.ScriptTypes, registry.ItemScriptTypes);
return new DynamicLibraryImpl(staticLibrary, registry.BattleStatCalculator, registry.DamageCalculator,
registry.MiscLibrary, registry.CaptureLibrary, scriptResolver);
var load = LibraryLoader.LoadPlugins(plugins);
return new DynamicLibraryImpl(load.staticLibrary, load.registry.BattleStatCalculator!,
load.registry.DamageCalculator!, load.registry.MiscLibrary!, load.registry.CaptureLibrary!, load.resolver);
}
private DynamicLibraryImpl(IStaticLibrary staticLibrary, IBattleStatCalculator statCalculator,

View File

@ -0,0 +1,87 @@
using PkmnLib.Dynamic.Libraries.DataLoaders;
using PkmnLib.Dynamic.ScriptHandling;
using PkmnLib.Dynamic.ScriptHandling.Registry;
using PkmnLib.Static.Libraries;
namespace PkmnLib.Dynamic.Libraries;
public static class LibraryLoader
{
public record LoadResult(ScriptRegistry registry, ScriptResolver resolver, IStaticLibrary staticLibrary);
public static LoadResult LoadPlugins(IEnumerable<Plugin> plugins)
{
var registry = new ScriptRegistry();
var orderedPlugins = plugins.OrderBy(x => x.LoadOrder).ToList();
var staticLibrary = CreateStaticLibrary(orderedPlugins);
foreach (var plugin in orderedPlugins)
{
plugin.Register(registry);
}
if (registry.DamageCalculator is null)
throw new InvalidOperationException("Damage calculator not found in plugins.");
if (registry.BattleStatCalculator is null)
throw new InvalidOperationException("Stat calculator not found in plugins.");
if (registry.MiscLibrary is null)
throw new InvalidOperationException("Misc library not found in plugins.");
if (registry.CaptureLibrary is null)
throw new InvalidOperationException("Capture library not found in plugins.");
var scriptResolver = new ScriptResolver(registry.ScriptTypes, registry.ItemScriptTypes);
return new LoadResult(registry, scriptResolver, staticLibrary);
}
private static StaticLibraryImpl CreateStaticLibrary(IReadOnlyList<Plugin> plugins)
{
var resourceProviders = plugins.OfType<IResourceProvider>().ToList();
var settings = resourceProviders.Select(x => x.Settings).LastOrDefault(x => x != null);
if (settings == null)
throw new InvalidOperationException("Settings not found.");
var typesResult = resourceProviders.Select(x => x.GetResource(ResourceFileType.Types))
.LastOrDefault(x => x != null);
if (typesResult == null)
throw new InvalidOperationException("Types resource not found.");
var naturesResult = resourceProviders.Select(x => x.GetResource(ResourceFileType.Natures))
.LastOrDefault(x => x != null);
if (naturesResult == null)
throw new InvalidOperationException("Natures resource not found.");
var movesResult = resourceProviders.Select(x => x.GetResource(ResourceFileType.Moves))
.LastOrDefault(x => x != null);
if (movesResult == null)
throw new InvalidOperationException("Moves resource not found.");
var itemsResult = resourceProviders.Select(x => x.GetResource(ResourceFileType.Items))
.LastOrDefault(x => x != null);
if (itemsResult == null)
throw new InvalidOperationException("Items resource not found.");
var abilitiesResult = resourceProviders.Select(x => x.GetResource(ResourceFileType.Abilities))
.LastOrDefault(x => x != null);
if (abilitiesResult == null)
throw new InvalidOperationException("Abilities resource not found.");
var growthRatesResult = resourceProviders.Select(x => x.GetResource(ResourceFileType.GrowthRates))
.LastOrDefault(x => x != null);
if (growthRatesResult == null)
throw new InvalidOperationException("Growth rates resource not found.");
var speciesResult = resourceProviders.Select(x => x.GetResource(ResourceFileType.Species))
.LastOrDefault(x => x != null);
if (speciesResult == null)
throw new InvalidOperationException("Species resource not found.");
// ReSharper disable once SuspiciousTypeConversion.Global
var mutators = plugins.OfType<IPluginDataMutator>().ToList();
var typesLibrary = TypeDataLoader.LoadTypeLibrary(typesResult);
var naturesLibrary = NatureDataLoader.LoadNatureLibrary(naturesResult);
var movesLibrary = MoveDataLoader.LoadMoves(movesResult, typesLibrary,
wrapper => mutators.ForEach(x => x.MutateMoveData(wrapper)));
var itemsLibrary = ItemDataLoader.LoadItems(itemsResult,
items => mutators.ForEach(x => x.MutateItemData(items)));
var abilitiesLibrary = AbilityDataLoader.LoadAbilities(abilitiesResult,
abilities => mutators.ForEach(x => x.MutateAbilityData(abilities)));
var growthRatesLibrary = GrowthRateDataLoader.LoadGrowthRates(growthRatesResult,
growthRates => mutators.ForEach(x => x.MutateGrowthRateData(growthRates)));
var speciesLibrary = SpeciesDataLoader.LoadSpecies(speciesResult, typesLibrary,
map => mutators.ForEach(x => x.MutateSpeciesData(map)));
return new StaticLibraryImpl(settings, speciesLibrary, movesLibrary, abilitiesLibrary, typesLibrary,
naturesLibrary, growthRatesLibrary, itemsLibrary);
}
}

View File

@ -16,8 +16,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentResults" Version="3.16.0"/>
<PackageReference Include="System.Collections.Immutable" Version="8.0.0"/>
<PackageReference Include="System.Text.Json" Version="8.0.5"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PkmnLib.Static\PkmnLib.Static.csproj"/>

View File

@ -38,6 +38,4 @@ public abstract class Plugin
/// <summary>
/// Base class for plugin configuration.
/// </summary>
public abstract class PluginConfiguration
{
}
public abstract class PluginConfiguration;

View File

@ -0,0 +1,13 @@
using PkmnLib.Dynamic.Libraries.DataLoaders.Models;
using PkmnLib.Static;
namespace PkmnLib.Dynamic.ScriptHandling.Registry;
public interface IPluginDataMutator
{
void MutateMoveData(SerializedMoveDataWrapper data);
void MutateItemData(List<SerializedItem> data);
void MutateAbilityData(Dictionary<string, SerializedAbility> data);
void MutateGrowthRateData(List<IGrowthRate> data);
void MutateSpeciesData(Dictionary<string, SerializedSpecies> data);
}

View File

@ -0,0 +1,28 @@
using PkmnLib.Static.Libraries;
namespace PkmnLib.Dynamic.ScriptHandling.Registry;
public interface IResourceProvider
{
LibrarySettings? Settings { get; }
Stream? GetResource(ResourceFileType request);
}
public enum ResourceFileType
{
Unknown,
Types,
Natures,
Moves,
Items,
Abilities,
GrowthRates,
Species,
}

View File

@ -12,8 +12,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{63C1
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PkmnLib.Plugin.Gen7.Tests", "Plugins\PkmnLib.Plugin.Gen7.Tests\PkmnLib.Plugin.Gen7.Tests.csproj", "{FBB53861-081F-4DAC-B006-79EE238D0DFC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PkmnLib.Dataloader", "PkmnLib.Dataloader\PkmnLib.Dataloader.csproj", "{E6A733FD-C2A3-4206-B9A9-40DBFBDBE1AC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFiles", "SolutionFiles", "{2B99ADF8-10E2-4A3D-906F-27DC8E312A79}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
@ -45,10 +43,6 @@ Global
{FBB53861-081F-4DAC-B006-79EE238D0DFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FBB53861-081F-4DAC-B006-79EE238D0DFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FBB53861-081F-4DAC-B006-79EE238D0DFC}.Release|Any CPU.Build.0 = Release|Any CPU
{E6A733FD-C2A3-4206-B9A9-40DBFBDBE1AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E6A733FD-C2A3-4206-B9A9-40DBFBDBE1AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E6A733FD-C2A3-4206-B9A9-40DBFBDBE1AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E6A733FD-C2A3-4206-B9A9-40DBFBDBE1AC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{FA5380F0-28CC-4AEC-8963-814B347A89BA} = {63C1B450-DC26-444A-AEBD-15979F3EEE53}

View File

@ -1,4 +1,4 @@
using PkmnLib.Dataloader;
using PkmnLib.Dynamic.Libraries.DataLoaders;
namespace PkmnLib.Tests.Dataloader;

View File

@ -1,4 +1,4 @@
using PkmnLib.Dataloader;
using PkmnLib.Dynamic.Libraries.DataLoaders;
namespace PkmnLib.Tests.Dataloader;

View File

@ -1,4 +1,4 @@
using PkmnLib.Dataloader;
using PkmnLib.Dynamic.Libraries.DataLoaders;
namespace PkmnLib.Tests.Dataloader;

View File

@ -1,4 +1,4 @@
using PkmnLib.Dataloader;
using PkmnLib.Dynamic.Libraries.DataLoaders;
using PkmnLib.Static.Libraries;
namespace PkmnLib.Tests.Dataloader;

View File

@ -1,4 +1,4 @@
using PkmnLib.Dataloader;
using PkmnLib.Dynamic.Libraries.DataLoaders;
namespace PkmnLib.Tests.Dataloader;

View File

@ -1,4 +1,4 @@
using PkmnLib.Dataloader;
using PkmnLib.Dynamic.Libraries.DataLoaders;
using PkmnLib.Static.Libraries;
namespace PkmnLib.Tests.Dataloader;

View File

@ -1,4 +1,4 @@
using PkmnLib.Dataloader;
using PkmnLib.Dynamic.Libraries.DataLoaders;
namespace PkmnLib.Tests.Dataloader;

View File

@ -1,5 +1,5 @@
using PkmnLib.Dataloader;
using PkmnLib.Dynamic.Libraries;
using PkmnLib.Dynamic.Libraries.DataLoaders;
using PkmnLib.Plugin.Gen7;
using PkmnLib.Static.Libraries;
@ -9,28 +9,7 @@ public static class LibraryHelpers
{
public static IDynamicLibrary LoadLibrary()
{
using var typesFile = File.Open("Data/Types.csv", FileMode.Open, FileAccess.Read, FileShare.Read);
var types = TypeDataLoader.LoadTypeLibrary(typesFile);
using var naturesFile = File.Open("Data/Natures.csv", FileMode.Open, FileAccess.Read, FileShare.Read);
var natures = NatureDataLoader.LoadNatureLibrary(naturesFile);
using var movesFile = File.Open("Data/Moves.jsonc", FileMode.Open, FileAccess.Read, FileShare.Read);
var moves = MoveDataLoader.LoadMoves(movesFile, types);
using var itemsFile = File.Open("Data/Items.json", FileMode.Open, FileAccess.Read, FileShare.Read);
var items = ItemDataLoader.LoadItems(itemsFile);
using var abilitiesFile = File.Open("Data/Abilities.json", FileMode.Open, FileAccess.Read, FileShare.Read);
var abilities = AbilityDataLoader.LoadAbilities(abilitiesFile);
using var growthRatesFile = File.Open("Data/GrowthRates.json", FileMode.Open, FileAccess.Read, FileShare.Read);
var growthRates = GrowthRateDataLoader.LoadGrowthRates(growthRatesFile);
using var speciesFile = File.Open("Data/Pokemon.json", FileMode.Open, FileAccess.Read, FileShare.Read);
var species = SpeciesDataLoader.LoadSpecies(speciesFile, types);
var staticLibrary = new StaticLibraryImpl(new LibrarySettings
{
MaxLevel = 100,
ShinyRate = 4096,
}, species, moves, abilities, types, natures, growthRates, items);
var dynamicLibrary = DynamicLibraryImpl.Create(staticLibrary, [
var dynamicLibrary = DynamicLibraryImpl.Create([
new Gen7Plugin(new Gen7PluginConfiguration
{
DamageCalculatorHasRandomness = false,

View File

@ -28,7 +28,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PkmnLib.Dataloader\PkmnLib.Dataloader.csproj"/>
<ProjectReference Include="..\PkmnLib.Dynamic\PkmnLib.Dynamic.csproj"/>
<ProjectReference Include="..\PkmnLib.Static\PkmnLib.Static.csproj"/>
<ProjectReference Include="..\Plugins\PkmnLib.Plugin.Gen7\PkmnLib.Plugin.Gen7.csproj"/>

View File

@ -1,6 +1,7 @@
using PkmnLib.Dynamic.Models;
using PkmnLib.Dynamic.ScriptHandling;
using PkmnLib.Plugin.Gen7.Libraries;
using PkmnLib.Plugin.Gen7.Libraries.Battling;
using PkmnLib.Static;
using PkmnLib.Static.Moves;

View File

@ -26,7 +26,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\PkmnLib.Dataloader\PkmnLib.Dataloader.csproj"/>
<ProjectReference Include="..\..\PkmnLib.Dynamic\PkmnLib.Dynamic.csproj"/>
<ProjectReference Include="..\PkmnLib.Plugin.Gen7\PkmnLib.Plugin.Gen7.csproj"/>
</ItemGroup>

View File

@ -0,0 +1,327 @@
{
"adaptability": {
"effect": "IncreasedStab"
},
"aerilate": {
"effect": "ChangeMoveType",
"parameters": {
"from": "normal",
"to": "flying"
}
},
"aftermath": {
"effect": "Aftermath"
},
"air_lock": {
"effect": "SuppressWeather"
},
"analytic": {
"effect": "Analytic"
},
"anger_point": {
"effect": "AngerPoint"
},
"anticipation": {
"effect": "Anticipation"
},
"arena_trap": {
"effect": "ArenaTrap"
},
"aroma_veil": {
"effect": "AromaVeil"
},
"aura_break": {
"effect": "AuraBreal"
},
"bad_dreams": {
"effect": "BadDreams"
},
"battery": {
"effect": "Battery"
},
"battle_armor": {
"effect": "PreventCritical"
},
"battle_bond": {
"effect": "BattleBond",
"flags": ["cant_be_changed"]
},
"beast_boost": {
"effect": "BeastBoost"
},
"berserk": {
"effect": "Berserk"
},
"big_pecks": {
"effect": "PreventDefLowering"
},
"blaze": {
"effect": "PowerUpType",
"parameters": {
"type": "fire"
}
},
"bulletproof": {
"effect": "Bulletproof"
},
"cheek_pouch": {
"effect": "CheekPouch"
},
"chlorophyll": {
"effect": "DoubleSpeedInWeather",
"parameters": {
"weather": "HarshSunlight"
}
},
"clear_body": {
"effect": "PreventStatLowering"
},
"cloud_nine": {
"effect": "SuppressWeather"
},
"color_change": {
"effect": "ColorChange"
},
"comatose": {
"flags": ["cant_be_changed"]
},
"competitive": {},
"compound_eyes": {},
"contrary": {},
"corrosion": {},
"cursed_body": {},
"cute_charm": {},
"damp": {},
"dancer": {},
"dark_aura": {},
"dazzling": {},
"defeatist": {},
"defiant": {},
"delta_stream": {},
"desolate_land": {},
"disguise": {
"flags": ["cant_be_changed", "cant_be_copied"]
},
"download": {},
"drizzle": {},
"drought": {},
"dry_skin": {},
"early_bird": {},
"effect_spore": {},
"electric_surge": {},
"emergency_exit": {},
"fairy_aura": {},
"filter": {},
"flame_body": {},
"flare_boost": {},
"flash_fire": {},
"flower_gift": {
"flags": ["cant_be_copied"]
},
"flower_veil": {},
"fluffy": {},
"forecast": {
"flags": ["cant_be_copied"]
},
"forewarn": {},
"friend_guard": {},
"frisk": {},
"full_metal_body": {},
"fur_coat": {},
"gale_wings": {},
"galvanize": {},
"gluttony": {},
"gooey": {},
"grass_pelt": {},
"grassy_surge": {},
"guts": {},
"harvest": {},
"healer": {},
"heatproof": {},
"heavy_metal": {},
"honey_gather": {},
"huge_power": {},
"hustle": {},
"hydration": {},
"hyper_cutter": {},
"ice_body": {},
"illuminate": {},
"illusion": {
"flags": ["cant_be_copied"]
},
"immunity": {},
"imposter": {
"flags": ["cant_be_copied"]
},
"infiltrator": {},
"innards_out": {},
"inner_focus": {},
"insomnia": {},
"intimidate": {},
"iron_barbs": {},
"iron_fist": {},
"justified": {},
"keen_eye": {},
"klutz": {},
"leaf_guard": {},
"levitate": {},
"light_metal": {},
"lightning_rod": {},
"limber": {},
"liquid_ooze": {},
"liquid_voice": {},
"long_reach": {},
"magic_bounce": {},
"magic_guard": {},
"magician": {},
"magma_armor": {},
"magnet_pull": {},
"marvel_scale": {},
"mega_launcher": {},
"merciless": {},
"minus": {},
"misty_surge": {},
"mold_breaker": {},
"moody": {},
"motor_drive": {},
"moxie": {},
"multiscale": {},
"multitype": {
"flags": ["cant_be_changed"]
},
"mummy": {},
"natural_cure": {},
"no_guard": {},
"normalize": {},
"oblivious": {},
"overcoat": {},
"overgrow": {},
"own_tempo": {},
"parental_bond": {},
"pickpocket": {},
"pickup": {},
"pixilate": {},
"plus": {},
"poison_heal": {},
"poison_point": {},
"poison_touch": {},
"power_construct": {
"flags": ["cant_be_changed", "cant_be_copied"]
},
"power_of_alchemy": {
"flags": ["cant_be_copied"]
},
"prankster": {},
"pressure": {},
"primordial_sea": {},
"prism_armor": {},
"protean": {},
"psychic_surge": {},
"pure_power": {},
"queenly_majesty": {},
"quick_feet": {},
"rain_dish": {},
"rattled": {},
"receiver": {
"flags": ["cant_be_copied"]
},
"reckless": {},
"refrigerate": {},
"regenerator": {},
"rivalry": {},
"rks_system": {
"flags": ["cant_be_changed"]
},
"rock_head": {},
"rough_skin": {},
"run_away": {},
"sand_force": {},
"sand_rush": {},
"sand_stream": {},
"sand_veil": {},
"sap_sipper": {},
"schooling": {
"flags": ["cant_be_changed"]
},
"scrappy": {},
"serene_grace": {},
"shadow_shield": {},
"shadow_tag": {},
"shed_skin": {},
"sheer_force": {},
"shell_armor": {},
"shield_dust": {},
"shields_down": {
"flags": ["cant_be_changed"]
},
"simple": {},
"skill_link": {},
"slow_start": {},
"slush_rush": {},
"sniper": {},
"snow_cloak": {},
"snow_warning": {},
"solar_power": {},
"solid_rock": {},
"soul_heart": {},
"soundproof": {},
"speed_boost": {},
"stakeout": {},
"stall": {},
"stamina": {},
"stance_change": {
"flags": ["cant_be_changed"]
},
"static": {},
"steadfast": {},
"steelworker": {},
"stench": {},
"sticky_hold": {},
"storm_drain": {},
"strong_jaw": {},
"sturdy": {},
"suction_cups": {},
"super_luck": {},
"surge_surfer": {},
"swarm": {},
"sweet_veil": {},
"swift_swim": {},
"symbiosis": {},
"synchronize": {},
"tangled_feet": {},
"tangling_hair": {},
"technician": {},
"telepathy": {},
"teravolt": {},
"thick_fat": {},
"tinted_lens": {},
"torrent": {},
"tough_claws": {},
"toxic_boost": {},
"trace": {
"flags": ["cant_be_copied"]
},
"triage": {},
"truant": {
"flags": ["cant_be_changed"]
},
"turboblaze": {},
"unaware": {},
"unburden": {},
"unnerve": {},
"victory_star": {},
"vital_spirit": {},
"volt_absorb": {},
"water_absorb": {},
"water_bubble": {},
"water_compaction": {},
"water_veil": {},
"weak_armor": {},
"white_smoke": {},
"wimp_out": {},
"wonder_guard": {},
"wonder_skin": {},
"zen_mode": {
"flags": ["cant_be_copied"]
}
}

View File

@ -0,0 +1,614 @@
{
"Erratic": [
0,
15,
52,
122,
237,
406,
637,
942,
1326,
1800,
2369,
3041,
3822,
4719,
5737,
6881,
8155,
9564,
11111,
12800,
14632,
16610,
18737,
21012,
23437,
26012,
28737,
31610,
34632,
37800,
41111,
44564,
48155,
51881,
55737,
59719,
63822,
68041,
72369,
76800,
81326,
85942,
90637,
95406,
100237,
105122,
110052,
115015,
120001,
125000,
131324,
137795,
144410,
151165,
158056,
165079,
172229,
179503,
186894,
194400,
202013,
209728,
217540,
225443,
233431,
241496,
249633,
257834,
267406,
276458,
286328,
296358,
305767,
316074,
326531,
336255,
346965,
357812,
367807,
378880,
390077,
400293,
411686,
423190,
433572,
445239,
457001,
467489,
479378,
491346,
501878,
513934,
526049,
536557,
548720,
560922,
571333,
583539,
591882,
600000
],
"Fast": [
0,
6,
21,
51,
100,
172,
274,
409,
583,
800,
1064,
1382,
1757,
2195,
2700,
3276,
3930,
4665,
5487,
6400,
7408,
8518,
9733,
11059,
12500,
14060,
15746,
17561,
19511,
21600,
23832,
26214,
28749,
31443,
34300,
37324,
40522,
43897,
47455,
51200,
55136,
59270,
63605,
68147,
72900,
77868,
83058,
88473,
94119,
100000,
106120,
112486,
119101,
125971,
133100,
140492,
148154,
156089,
164303,
172800,
181584,
190662,
200037,
209715,
219700,
229996,
240610,
251545,
262807,
274400,
286328,
298598,
311213,
324179,
337500,
351180,
365226,
379641,
394431,
409600,
425152,
441094,
457429,
474163,
491300,
508844,
526802,
545177,
563975,
583200,
602856,
622950,
643485,
664467,
685900,
707788,
730138,
752953,
776239,
800000
],
"MediumFast": [
0,
8,
27,
64,
125,
216,
343,
512,
729,
1000,
1331,
1728,
2197,
2744,
3375,
4096,
4913,
5832,
6859,
8000,
9261,
10648,
12167,
13824,
15625,
17576,
19683,
21952,
24389,
27000,
29791,
32768,
35937,
39304,
42875,
46656,
50653,
54872,
59319,
64000,
68921,
74088,
79507,
85184,
91125,
97336,
103823,
110592,
117649,
125000,
132651,
140608,
148877,
157464,
166375,
175616,
185193,
195112,
205379,
216000,
226981,
238328,
250047,
262144,
274625,
287496,
300763,
314432,
328509,
343000,
357911,
373248,
389017,
405224,
421875,
438976,
456533,
474552,
493039,
512000,
531441,
551368,
571787,
592704,
614125,
636056,
658503,
681472,
704969,
729000,
753571,
778688,
804357,
830584,
857375,
884736,
912673,
941192,
970299,
1000000
],
"MediumSlow": [
0,
9,
57,
96,
135,
179,
236,
314,
419,
560,
742,
973,
1261,
1612,
2035,
2535,
3120,
3798,
4575,
5460,
6458,
7577,
8825,
10208,
11735,
13411,
15244,
17242,
19411,
21760,
24294,
27021,
29949,
33084,
36435,
40007,
43808,
47846,
52127,
56660,
61450,
66505,
71833,
77440,
83335,
89523,
96012,
102810,
109923,
117360,
125126,
133229,
141677,
150476,
159635,
169159,
179056,
189334,
199999,
211060,
222522,
234393,
246681,
259392,
272535,
286115,
300140,
314618,
329555,
344960,
360838,
377197,
394045,
411388,
429235,
447591,
466464,
485862,
505791,
526260,
547274,
568841,
590969,
613664,
636935,
660787,
685228,
710266,
735907,
762160,
789030,
816525,
844653,
873420,
902835,
932903,
963632,
995030,
1027103,
1059860
],
"Slow": [
0,
10,
33,
80,
156,
270,
428,
640,
911,
1250,
1663,
2160,
2746,
3430,
4218,
5120,
6141,
7290,
8573,
10000,
11576,
13310,
15208,
17280,
19531,
21970,
24603,
27440,
30486,
33750,
37238,
40960,
44921,
49130,
53593,
58320,
63316,
68590,
74148,
80000,
86151,
92610,
99383,
106480,
113906,
121670,
129778,
138240,
147061,
156250,
165813,
175760,
186096,
196830,
207968,
219520,
231491,
243890,
256723,
270000,
283726,
297910,
312558,
327680,
343281,
359370,
375953,
393040,
410636,
428750,
447388,
466560,
486271,
506530,
527343,
548720,
570666,
593190,
616298,
640000,
664301,
689210,
714733,
740880,
767656,
795070,
823128,
851840,
881211,
911250,
941963,
973360,
1005446,
1038230,
1071718,
1105920,
1140841,
1176490,
1212873,
1250000
],
"Fluctuating": [
0,
4,
13,
32,
65,
112,
178,
276,
393,
540,
745,
967,
1230,
1591,
1957,
2457,
3046,
3732,
4526,
5440,
6482,
7666,
9003,
10506,
12187,
14060,
16140,
18439,
20974,
23760,
26811,
30146,
33780,
37731,
42017,
46656,
50653,
55969,
60505,
66560,
71677,
78533,
84277,
91998,
98415,
107069,
114205,
123863,
131766,
142500,
151222,
163105,
172697,
185807,
196322,
210739,
222231,
238036,
250562,
267840,
281456,
300293,
315059,
335544,
351520,
373744,
390991,
415050,
433631,
459620,
479600,
507617,
529063,
559209,
582187,
614566,
639146,
673863,
700115,
737280,
765275,
804997,
834809,
877201,
908905,
954084,
987754,
1035837,
1071552,
1122660,
1160499,
1214753,
1254796,
1312322,
1354652,
1415577,
1460276,
1524731,
1571884,
1640000
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
Name|Increased|Decreased
Hardy||
Lonely|Attack|Defense
Brave|Attack|Speed
Adamant|Attack|SpecialAttack
Naughty|Attack|SpecialDefense
Bold|Defense|Attack
Docile||
Relaxed|Defense|Speed
Impish|Defense|SpecialAttack
Lax|Defense|SpecialDefense
Timid|Speed|Attack
Hasty|Speed|Defense
Serious||
Jolly|Speed|SpecialAttack
Naive|Speed|SpecialDefense
Modest|SpecialAttack|Attack
Mild|SpecialAttack|Defense
Quiet|SpecialAttack|Speed
Bashful||
Rash|SpecialAttack|SpecialDefense
Calm|SpecialDefense|Attack
Gentle|SpecialDefense|Defense
Sassy|SpecialDefense|Speed
Careful|SpecialDefense|SpecialAttack
Quirky||
1 Name Increased Decreased
2 Hardy
3 Lonely Attack Defense
4 Brave Attack Speed
5 Adamant Attack SpecialAttack
6 Naughty Attack SpecialDefense
7 Bold Defense Attack
8 Docile
9 Relaxed Defense Speed
10 Impish Defense SpecialAttack
11 Lax Defense SpecialDefense
12 Timid Speed Attack
13 Hasty Speed Defense
14 Serious
15 Jolly Speed SpecialAttack
16 Naive Speed SpecialDefense
17 Modest SpecialAttack Attack
18 Mild SpecialAttack Defense
19 Quiet SpecialAttack Speed
20 Bashful
21 Rash SpecialAttack SpecialDefense
22 Calm SpecialDefense Attack
23 Gentle SpecialDefense Defense
24 Sassy SpecialDefense Speed
25 Careful SpecialDefense SpecialAttack
26 Quirky

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
Types|Normal|Fighting|Flying|Poison|Ground|Rock|Bug|Ghost|Steel|Fire|Water|Grass|Electric|Psychic|Ice|Dragon|Dark|Fairy
Normal|1|1|1|1|1|0.5|1|0|0.5|1|1|1|1|1|1|1|1|1
Fighting|2|1|0.5|0.5|1|2|0.5|0|2|1|1|1|1|0.5|2|1|2|0.5
Flying|1|2|1|1|1|0.5|2|1|0.5|1|1|2|0.5|1|1|1|1|1
Poison|1|1|1|0.5|0.5|0.5|1|0.5|0|1|1|2|1|1|1|1|1|2
Ground|1|1|0|2|1|2|0.5|1|2|2|1|0.5|2|1|1|1|1|1
Rock|1|0.5|2|1|0.5|1|2|1|0.5|2|1|1|1|1|2|1|1|1
Bug|1|0.5|0.5|0.5|1|1|1|0.5|0.5|0.5|1|2|1|2|1|1|2|0.5
Ghost|0|1|1|1|1|1|1|2|1|1|1|1|1|2|1|1|0.5|1
Steel|1|1|1|1|1|2|1|1|0.5|0.5|0.5|1|0.5|1|2|1|1|2
Fire|1|1|1|1|1|0.5|2|1|2|0.5|0.5|2|1|1|2|0.5|1|1
Water|1|1|1|1|2|2|1|1|1|2|0.5|0.5|1|1|1|0.5|1|1
Grass|1|1|0.5|0.5|2|2|0.5|1|0.5|0.5|2|0.5|1|1|1|0.5|1|1
Electric|1|1|2|1|0|1|1|1|1|1|2|0.5|0.5|1|1|0.5|1|1
Psychic|1|2|1|2|1|1|1|1|0.5|1|1|1|1|0.5|1|1|0|1
Ice|1|1|2|1|2|1|1|1|0.5|0.5|0.5|2|1|1|0.5|2|1|1
Dragon|1|1|1|1|1|1|1|1|0.5|1|1|1|1|1|1|2|1|0
Dark|1|0.5|1|1|1|1|1|2|1|1|1|1|1|2|1|1|0.5|0.5
Fairy|1|2|1|0.5|1|1|1|1|0.5|0.5|1|1|1|1|1|2|2|1
1 Types Normal Fighting Flying Poison Ground Rock Bug Ghost Steel Fire Water Grass Electric Psychic Ice Dragon Dark Fairy
2 Normal 1 1 1 1 1 0.5 1 0 0.5 1 1 1 1 1 1 1 1 1
3 Fighting 2 1 0.5 0.5 1 2 0.5 0 2 1 1 1 1 0.5 2 1 2 0.5
4 Flying 1 2 1 1 1 0.5 2 1 0.5 1 1 2 0.5 1 1 1 1 1
5 Poison 1 1 1 0.5 0.5 0.5 1 0.5 0 1 1 2 1 1 1 1 1 2
6 Ground 1 1 0 2 1 2 0.5 1 2 2 1 0.5 2 1 1 1 1 1
7 Rock 1 0.5 2 1 0.5 1 2 1 0.5 2 1 1 1 1 2 1 1 1
8 Bug 1 0.5 0.5 0.5 1 1 1 0.5 0.5 0.5 1 2 1 2 1 1 2 0.5
9 Ghost 0 1 1 1 1 1 1 2 1 1 1 1 1 2 1 1 0.5 1
10 Steel 1 1 1 1 1 2 1 1 0.5 0.5 0.5 1 0.5 1 2 1 1 2
11 Fire 1 1 1 1 1 0.5 2 1 2 0.5 0.5 2 1 1 2 0.5 1 1
12 Water 1 1 1 1 2 2 1 1 1 2 0.5 0.5 1 1 1 0.5 1 1
13 Grass 1 1 0.5 0.5 2 2 0.5 1 0.5 0.5 2 0.5 1 1 1 0.5 1 1
14 Electric 1 1 2 1 0 1 1 1 1 1 2 0.5 0.5 1 1 0.5 1 1
15 Psychic 1 2 1 2 1 1 1 1 0.5 1 1 1 1 0.5 1 1 0 1
16 Ice 1 1 2 1 2 1 1 1 0.5 0.5 0.5 2 1 1 0.5 2 1 1
17 Dragon 1 1 1 1 1 1 1 1 0.5 1 1 1 1 1 1 2 1 0
18 Dark 1 0.5 1 1 1 1 1 2 1 1 1 1 1 2 1 1 0.5 0.5
19 Fairy 1 2 1 0.5 1 1 1 1 0.5 0.5 1 1 1 1 1 2 2 1

View File

@ -1,4 +1,9 @@
using System;
using System.ComponentModel;
using System.IO;
using PkmnLib.Plugin.Gen7.Libraries;
using PkmnLib.Plugin.Gen7.Libraries.Battling;
using PkmnLib.Static.Libraries;
namespace PkmnLib.Plugin.Gen7;
@ -7,7 +12,7 @@ public class Gen7PluginConfiguration : PluginConfiguration
public bool DamageCalculatorHasRandomness { get; set; } = true;
}
public class Gen7Plugin : Dynamic.ScriptHandling.Registry.Plugin
public class Gen7Plugin : Dynamic.ScriptHandling.Registry.Plugin, IResourceProvider
{
private readonly Gen7PluginConfiguration _configuration;
@ -37,4 +42,34 @@ public class Gen7Plugin : Dynamic.ScriptHandling.Registry.Plugin
registry.RegisterMiscLibrary(new Gen7MiscLibrary());
registry.RegisterCaptureLibrary(new Gen7CaptureLibrary());
}
/// <inheritdoc />
public LibrarySettings? Settings => new()
{
MaxLevel = 100,
ShinyRate = 4096,
};
/// <inheritdoc />
Stream? IResourceProvider.GetResource(ResourceFileType request)
{
return request switch
{
ResourceFileType.Types => typeof(Gen7Plugin).Assembly.GetManifestResourceStream(
"PkmnLib.Plugin.Gen7.Data.Types.csv"),
ResourceFileType.Natures => typeof(Gen7Plugin).Assembly.GetManifestResourceStream(
"PkmnLib.Plugin.Gen7.Data.Natures.csv"),
ResourceFileType.Moves => typeof(Gen7Plugin).Assembly.GetManifestResourceStream(
"PkmnLib.Plugin.Gen7.Data.Moves.jsonc"),
ResourceFileType.Items => typeof(Gen7Plugin).Assembly.GetManifestResourceStream(
"PkmnLib.Plugin.Gen7.Data.Items.json"),
ResourceFileType.Abilities => typeof(Gen7Plugin).Assembly.GetManifestResourceStream(
"PkmnLib.Plugin.Gen7.Data.Abilities.json"),
ResourceFileType.GrowthRates => typeof(Gen7Plugin).Assembly.GetManifestResourceStream(
"PkmnLib.Plugin.Gen7.Data.GrowthRates.json"),
ResourceFileType.Species => typeof(Gen7Plugin).Assembly.GetManifestResourceStream(
"PkmnLib.Plugin.Gen7.Data.Pokemon.json"),
_ => throw new ArgumentOutOfRangeException(nameof(request), request, null),
};
}
}

View File

@ -1,7 +1,7 @@
using System;
using PkmnLib.Dynamic.Libraries;
namespace PkmnLib.Plugin.Gen7.Libraries;
namespace PkmnLib.Plugin.Gen7.Libraries.Battling;
public class Gen7BattleStatCalculator : IBattleStatCalculator
{

View File

@ -1,7 +1,7 @@
using System;
using PkmnLib.Dynamic.Libraries;
namespace PkmnLib.Plugin.Gen7.Libraries;
namespace PkmnLib.Plugin.Gen7.Libraries.Battling;
public class Gen7CaptureLibrary : ICaptureLibrary
{

View File

@ -3,7 +3,7 @@ using System.Linq;
using PkmnLib.Dynamic.Libraries;
using PkmnLib.Static.Moves;
namespace PkmnLib.Plugin.Gen7.Libraries;
namespace PkmnLib.Plugin.Gen7.Libraries.Battling;
public class Gen7DamageCalculator(bool hasRandomness) : IDamageCalculator
{

View File

@ -5,7 +5,7 @@ using PkmnLib.Dynamic.Libraries;
using PkmnLib.Static.Moves;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Libraries;
namespace PkmnLib.Plugin.Gen7.Libraries.Battling;
public class Gen7MiscLibrary : IMiscLibrary
{

View File

@ -11,4 +11,7 @@
<ProjectReference Include="..\..\PkmnLib.Static\PkmnLib.Static.csproj"/>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Data\*.*"/>
</ItemGroup>
</Project>