using System.Collections.Immutable; using System.Text.Json; using PkmnLib.Dynamic.Libraries.DataLoaders.Models; using PkmnLib.Static; using PkmnLib.Static.Libraries; using PkmnLib.Static.Moves; using PkmnLib.Static.Utils; namespace PkmnLib.Dynamic.Libraries.DataLoaders; /// /// Loads move data from a JSON file. /// public static class MoveDataLoader { /// /// Loads move data from a stream. /// public static MoveLibrary LoadMoves(Stream stream, TypeLibrary typeLibrary, Action? onAfterLoad = null) { var library = new MoveLibrary(); var objects = JsonSerializer.Deserialize(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); return library; } /// /// Factory delegate for creating moves. /// public delegate MoveDataImpl MoveFactoryDelegate(SerializedMove serialized, StringKey name, TypeIdentifier type, MoveCategory category, byte basePower, byte accuracy, byte pp, MoveTarget target, sbyte priority, ISecondaryEffect? secondaryEffect, IEnumerable flags); /// /// The move constructor. This is used to create moves from the JSON data. /// [PublicAPI] public static MoveFactoryDelegate MoveConstructor = (_, name, moveType, category, basePower, accuracy, baseUsages, target, priority, secondaryEffect, flags) => new MoveDataImpl(name, moveType, category, basePower, accuracy, baseUsages, target, priority, secondaryEffect, flags); private static MoveDataImpl DeserializeMove(SerializedMove serialized, TypeLibrary typeLibrary) { var type = serialized.Type; var power = serialized.Power; var pp = serialized.PP; var accuracy = serialized.Accuracy; var priority = serialized.Priority; var target = serialized.Target; var category = serialized.Category; var flags = serialized.Flags; var effect = serialized.Effect; if (target.Equals("self", StringComparison.InvariantCultureIgnoreCase)) target = "selfUse"; if (!typeLibrary.TryGetTypeIdentifier(type, out var typeIdentifier)) throw new InvalidDataException($"Type {type} is not a valid type."); if (!Enum.TryParse(category, true, out var categoryEnum)) throw new InvalidDataException($"Category {category} is not a valid category."); if (!Enum.TryParse(target, true, out var targetEnum)) throw new InvalidDataException($"Target {target} is not a valid target."); var secondaryEffect = effect.ParseEffect(); var move = MoveConstructor(serialized, serialized.Name, typeIdentifier, categoryEnum, power, accuracy, pp, targetEnum, priority, secondaryEffect, flags.Select(x => (StringKey)x).ToImmutableHashSet()); return move; } }