diff --git a/PkmnLib.Dynamic/Models/Pokemon.cs b/PkmnLib.Dynamic/Models/Pokemon.cs
index a9c21b9..d32af67 100644
--- a/PkmnLib.Dynamic/Models/Pokemon.cs
+++ b/PkmnLib.Dynamic/Models/Pokemon.cs
@@ -400,8 +400,8 @@ public class PokemonImpl : ScriptSource, IPokemon
WeightInKg = form.Weight;
HeightInMeters = form.Height;
Happiness = serializedPokemon.Happiness;
- IndividualValues = new IndividualValueStatisticSet(serializedPokemon.IndividualValues);
- EffortValues = new EffortValueStatisticSet(serializedPokemon.EffortValues);
+ IndividualValues = serializedPokemon.IndividualValues.ToIndividualValueStatisticSet();
+ EffortValues = serializedPokemon.EffortValues.ToEffortValueStatisticSet();
if (!library.StaticLibrary.Natures.TryGet(serializedPokemon.Nature, out var nature))
throw new KeyNotFoundException($"Nature {serializedPokemon.Nature} not found.");
Nature = nature;
diff --git a/PkmnLib.Dynamic/Models/Serialized/SerializedPokemon.cs b/PkmnLib.Dynamic/Models/Serialized/SerializedPokemon.cs
index afb4d8a..c9f4e79 100644
--- a/PkmnLib.Dynamic/Models/Serialized/SerializedPokemon.cs
+++ b/PkmnLib.Dynamic/Models/Serialized/SerializedPokemon.cs
@@ -4,10 +4,17 @@ using PkmnLib.Static.Species;
namespace PkmnLib.Dynamic.Models.Serialized;
-public class SerializedPokemon
+///
+/// A serialized Pokémon is a representation of a Pokémon that can be easily serialized and deserialized.
+///
+public record SerializedPokemon
{
- public SerializedPokemon(){}
-
+ ///
+ public SerializedPokemon()
+ {
+ }
+
+ ///
[SetsRequiredMembers]
public SerializedPokemon(IPokemon pokemon)
{
@@ -21,8 +28,8 @@ public class SerializedPokemon
HeldItem = pokemon.HeldItem?.Name;
CurrentHealth = pokemon.CurrentHealth;
Happiness = pokemon.Happiness;
- IndividualValues = new IndividualValueStatisticSet(pokemon.IndividualValues);
- EffortValues = new EffortValueStatisticSet(pokemon.EffortValues);
+ IndividualValues = new SerializedStats(pokemon.IndividualValues);
+ EffortValues = new SerializedStats(pokemon.EffortValues);
Nature = pokemon.Nature.Name;
Nickname = pokemon.Nickname;
Ability = pokemon.Form.GetAbility(pokemon.AbilityIndex);
@@ -41,31 +48,141 @@ public class SerializedPokemon
IsEgg = pokemon.IsEgg;
Status = pokemon.StatusScript.Script?.Name;
}
-
+
+ ///
public required string Species { get; set; }
+
+ ///
public required string Form { get; set; }
+
+ ///
public LevelInt Level { get; set; }
+
+ ///
public uint Experience { get; set; }
+
+ ///
public uint PersonalityValue { get; set; }
+
+ ///
public Gender Gender { get; set; }
+
+ ///
public byte Coloring { get; set; }
+
+ ///
public string? HeldItem { get; set; }
+
+ ///
public uint CurrentHealth { get; set; }
+
+ ///
public byte Happiness { get; set; }
- public required IndividualValueStatisticSet IndividualValues { get; set; }
- public required EffortValueStatisticSet EffortValues { get; set; }
+
+ ///
+ public required SerializedStats IndividualValues { get; set; }
+
+ ///
+ public required SerializedStats EffortValues { get; set; }
+
+ ///
public required string Nature { get; set; }
+
+ ///
public string? Nickname { get; set; }
+
+ ///
+ /// The ability of the Pokémon. Note that this is the ability name, not the ability index, as the ability index might
+ /// change if the order of abilities changes in data.
+ ///
public required string Ability { get; set; }
+
+ ///
public required SerializedLearnedMove?[] Moves { get; set; }
+
+ ///
public bool AllowedExperience { get; set; }
+
+ ///
public bool IsEgg { get; set; }
+
+ ///
+ /// The status of the Pokémon. This is the name of the status script, if any exists.
+ ///
public string? Status { get; set; }
}
-public class SerializedLearnedMove
+///
+/// A serialized learned move is a representation of a learned move that can be easily serialized and deserialized.
+///
+public record SerializedLearnedMove
{
+ ///
+ /// The name of the move.
+ ///
public required string MoveName { get; set; }
+
+ ///
public required MoveLearnMethod LearnMethod { get; set; }
+
+ ///
public required byte CurrentPp { get; set; }
+}
+
+public record SerializedStats
+{
+ public SerializedStats()
+ {
+ }
+
+ public SerializedStats(ImmutableStatisticSet stats)
+ {
+ Hp = stats.Hp;
+ Attack = stats.Attack;
+ Defense = stats.Defense;
+ SpecialAttack = stats.SpecialAttack;
+ SpecialDefense = stats.SpecialDefense;
+ Speed = stats.Speed;
+ }
+
+ public SerializedStats(long hp, long attack, long defense, long specialAttack, long specialDefense, long speed)
+ {
+ Hp = hp;
+ Attack = attack;
+ Defense = defense;
+ SpecialAttack = specialAttack;
+ SpecialDefense = specialDefense;
+ Speed = speed;
+ }
+
+ public long Hp { get; set; }
+ public long Attack { get; set; }
+ public long Defense { get; set; }
+ public long SpecialAttack { get; set; }
+ public long SpecialDefense { get; set; }
+ public long Speed { get; set; }
+
+ public IndividualValueStatisticSet ToIndividualValueStatisticSet()
+ {
+ if (Hp < 0 || Attack < 0 || Defense < 0 || SpecialAttack < 0 || SpecialDefense < 0 || Speed < 0)
+ throw new InvalidOperationException("Stats cannot be negative.");
+ if (Hp > byte.MaxValue || Attack > byte.MaxValue || Defense > byte.MaxValue || SpecialAttack > byte.MaxValue ||
+ SpecialDefense > byte.MaxValue || Speed > byte.MaxValue)
+ throw new InvalidOperationException("Stats cannot be higher than 255.");
+
+ return new IndividualValueStatisticSet((byte)Hp, (byte)Attack, (byte)Defense, (byte)SpecialAttack,
+ (byte)SpecialDefense, (byte)Speed);
+ }
+
+ public EffortValueStatisticSet ToEffortValueStatisticSet()
+ {
+ if (Hp < 0 || Attack < 0 || Defense < 0 || SpecialAttack < 0 || SpecialDefense < 0 || Speed < 0)
+ throw new InvalidOperationException("Stats cannot be negative.");
+ if (Hp > byte.MaxValue || Attack > byte.MaxValue || Defense > byte.MaxValue || SpecialAttack > byte.MaxValue ||
+ SpecialDefense > byte.MaxValue || Speed > byte.MaxValue)
+ throw new InvalidOperationException("Stats cannot be higher than 255.");
+
+ return new EffortValueStatisticSet((byte)Hp, (byte)Attack, (byte)Defense, (byte)SpecialAttack,
+ (byte)SpecialDefense, (byte)Speed);
+ }
}
\ No newline at end of file
diff --git a/PkmnLib.Static/StatisticSet.cs b/PkmnLib.Static/StatisticSet.cs
index f25a878..32fe807 100644
--- a/PkmnLib.Static/StatisticSet.cs
+++ b/PkmnLib.Static/StatisticSet.cs
@@ -334,7 +334,7 @@ public record IndividualValueStatisticSet : ClampedStatisticSet
public IndividualValueStatisticSet() : base(0, 0, 0, 0, 0, 0)
{
}
-
+
///
public IndividualValueStatisticSet(byte hp, byte attack, byte defense, byte specialAttack, byte specialDefense,
byte speed) : base(hp, attack, defense, specialAttack, specialDefense, speed)
diff --git a/PkmnLib.Tests/Dynamic/SerializationTests.cs b/PkmnLib.Tests/Dynamic/SerializationTests.cs
index 8c14698..37d6cca 100644
--- a/PkmnLib.Tests/Dynamic/SerializationTests.cs
+++ b/PkmnLib.Tests/Dynamic/SerializationTests.cs
@@ -1,3 +1,4 @@
+using System.Text.Json;
using PkmnLib.Dynamic.Models;
using PkmnLib.Dynamic.Models.Serialized;
using PkmnLib.Static;
@@ -65,8 +66,8 @@ public class SerializationTests
HeldItem = null,
CurrentHealth = 29,
Happiness = 70,
- IndividualValues = new IndividualValueStatisticSet(20, 20, 20, 20, 20, 20),
- EffortValues = new EffortValueStatisticSet(0, 0, 0, 0, 0, 0),
+ IndividualValues = new SerializedStats(20, 20, 20, 20, 20, 20),
+ EffortValues = new SerializedStats(0, 0, 0, 0, 0, 0),
Nature = "hardy",
Nickname = "foo",
Moves = new[]
@@ -112,4 +113,70 @@ public class SerializationTests
});
}
+ [Test]
+ public void SerializedPokemonToJson()
+ {
+ var data = new SerializedPokemon
+ {
+ Species = "bulbasaur",
+ Form = "default",
+ Ability = "overgrow",
+ Level = 10,
+ Experience = 560,
+ PersonalityValue = 1000,
+ Gender = Gender.Male,
+ Coloring = 0,
+ HeldItem = null,
+ CurrentHealth = 29,
+ Happiness = 70,
+ IndividualValues = new SerializedStats(20, 20, 20, 20, 20, 20),
+ EffortValues = new SerializedStats(0, 0, 0, 0, 0, 0),
+ Nature = "hardy",
+ Nickname = "foo",
+ Moves = new[]
+ {
+ new SerializedLearnedMove
+ {
+ MoveName = "tackle",
+ LearnMethod = MoveLearnMethod.LevelUp,
+ CurrentPp = 23,
+ },
+ null,
+ null,
+ null,
+ },
+ };
+
+ var json = JsonSerializer.Serialize(data);
+ var deserialized = JsonSerializer.Deserialize(json);
+ Assert.That(deserialized, Is.Not.Null);
+ Assert.Multiple(() =>
+ {
+ Assert.That(deserialized!.Species, Is.EqualTo("bulbasaur"));
+ Assert.That(deserialized!.Form, Is.EqualTo("default"));
+ Assert.That(deserialized!.Ability, Is.EqualTo("overgrow"));
+ Assert.That(deserialized!.Level, Is.EqualTo(10));
+ Assert.That(deserialized!.Experience, Is.EqualTo(560));
+ Assert.That(deserialized!.PersonalityValue, Is.EqualTo(1000));
+ Assert.That(deserialized!.Gender, Is.EqualTo(Gender.Male));
+ Assert.That(deserialized!.Coloring, Is.EqualTo(0));
+ Assert.That(deserialized!.HeldItem, Is.Null);
+ Assert.That(deserialized!.CurrentHealth, Is.EqualTo(29));
+ Assert.That(deserialized!.Happiness, Is.EqualTo(70));
+ Assert.That(deserialized!.IndividualValues, Is.EqualTo(new SerializedStats(20, 20, 20, 20, 20, 20)));
+ Assert.That(deserialized!.EffortValues, Is.EqualTo(new SerializedStats(0, 0, 0, 0, 0, 0)));
+ Assert.That(deserialized!.Nature, Is.EqualTo("hardy"));
+ Assert.That(deserialized!.Nickname, Is.EqualTo("foo"));
+ });
+
+ Assert.That(deserialized!.Moves, Has.Length.EqualTo(4));
+ Assert.That(deserialized!.Moves[0], Is.Not.Null);
+ Assert.Multiple(() =>
+ {
+ Assert.That(deserialized!.Moves[0]!.MoveName, Is.EqualTo("tackle"));
+ Assert.That(deserialized!.Moves[0]!.LearnMethod, Is.EqualTo(MoveLearnMethod.LevelUp));
+ Assert.That(deserialized!.Moves[0]!.CurrentPp, Is.EqualTo(23));
+ });
+ }
+
}
\ No newline at end of file