PkmnLibRSharp/PkmnLibRSharp/DynamicData/PokemonParty.cs

102 lines
3.7 KiB
C#

using System.Collections;
using System.Collections.Generic;
using PkmnLibSharp.Utils;
using Interface = PkmnLibSharp.FFI.DynamicData.PokemonParty;
namespace PkmnLibSharp.DynamicData
{
/// <summary>
/// A list of Pokemon belonging to a trainer.
/// </summary>
public class PokemonParty : HandleType, IReadOnlyList<Pokemon?>
{
/// <summary>
/// A cache of the Pokemon in the party.
/// </summary>
private Pokemon?[] _cachedPokemon = null!;
internal PokemonParty(FFIHandle handle) : base(handle)
{
}
/// <summary>
/// Instantiates a party with a set size.
/// </summary>
/// <param name="capacity">The length of the party</param>
public static PokemonParty Create(ulong capacity)
{
var handle = Interface.pokemon_party_new(capacity).Resolve();
var party = Resolver.Instance.ResolvePokemonParty(handle);
party._cachedPokemon = new Pokemon?[capacity];
return party;
}
/// <inheritdoc />
public IEnumerator<Pokemon?> GetEnumerator()
{
return ((IEnumerable<Pokemon?>)_cachedPokemon).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
/// <inheritdoc />
public int Count => _cachedPokemon.Length;
/// <inheritdoc />
public Pokemon? this[int index] => _cachedPokemon[index];
/// <summary>
/// Swaps two Pokemon in the party around.
/// </summary>
public void Switch(int a, int b)
{
Interface.pokemon_party_switch(Handle, (ulong)a, (ulong)b).Result();
(_cachedPokemon[a], _cachedPokemon[b]) = (_cachedPokemon[b], _cachedPokemon[a]);
}
/// <summary>
/// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon.
/// </summary>
/// <param name="index">The index to switch at</param>
/// <param name="pokemon">The pokemon to switch into the slot</param>
/// <returns>The previous Pokemon in the slot</returns>
public Pokemon? SwapInto(int index, Pokemon? pokemon)
{
var handle = Interface.pokemon_party_swap_into(Handle, (ulong)index, pokemon?.Handle ?? FFIHandle.Zero)
.Result();
var p = handle.IsNull ? null : Resolver.Instance.ResolvePokemon(handle.Resolve());
_cachedPokemon[index] = pokemon;
return p;
}
/// <summary>
/// Whether or not the party still has Pokemon that can be used in battle.
/// </summary>
public bool HasUsablePokemon() => Interface.pokemon_party_has_usable_pokemon(Handle) == 1;
/// <summary>
/// Checks if the party contains a given pokemon.
/// </summary>
/// <param name="pokemon">The pokemon to check for</param>
public bool HasPokemon(Pokemon pokemon) => Interface.pokemon_party_has_pokemon(Handle, pokemon.Handle) == 1;
/// <summary>
/// Makes sure there are no empty spots in the party anymore, leaving the length the same.
/// </summary>
public void PackParty()
{
Interface.pokemon_party_pack_party(Handle);
// Ensure the old cache is kept alive while we update the new one.
var oldCache = _cachedPokemon;
// Update the cache.
_cachedPokemon = new Pokemon?[oldCache.Length];
for (var i = 0; i < oldCache.Length; i++)
{
var handle = Interface.pokemon_party_at(Handle, (ulong)i).Resolve();
_cachedPokemon[i] = Resolver.Instance.ResolvePokemon(handle);
}
}
}
}