Minor xmldoc / usage updates

This commit is contained in:
Kurt 2021-02-21 15:01:28 -08:00
parent c11cf3d6d4
commit 41096fb56e
24 changed files with 247 additions and 122 deletions

View file

@ -137,7 +137,7 @@ namespace PKHeX.Core
otname.CopyTo(pk2.otname, 0);
nick.CopyTo(pk2.nick, 0);
pk2.HeldItem = ItemConverter.GetItemFuture1(pk2.HeldItem);
pk2.HeldItem = Gen2Item;
pk2.CurrentFriendship = pk2.PersonalInfo.BaseFriendship;
pk2.Stat_Level = CurrentLevel;

View file

@ -7,7 +7,8 @@ namespace PKHeX.Core
{
public override PersonalInfo PersonalInfo => PersonalTable.C[Species];
public override bool Valid => Species <= 252;
internal const byte EggSpeciesValue = 0xFD;
public override bool Valid => Species is <= Legal.MaxSpeciesID_2 or EggSpeciesValue; // egg
public override int SIZE_PARTY => PokeCrypto.SIZE_2PARTY;
public override int SIZE_STORED => PokeCrypto.SIZE_2STORED;

View file

@ -2,7 +2,7 @@ namespace PKHeX.Core
{
public sealed class PokeList2 : PokeListGB<PK2>
{
protected override byte GetSpeciesBoxIdentifier(PK2 pk) => pk.IsEgg ? 0xFD : (byte)pk.Species;
protected override byte GetSpeciesBoxIdentifier(PK2 pk) => pk.IsEgg ? PK2.EggSpeciesValue : (byte)pk.Species;
protected override PK2 GetEntry(byte[] dat, byte[] otname, byte[] nick, bool egg) => new(dat, Japanese) { OT_Trash = otname, Nickname_Trash = nick, IsEgg = egg };
protected override int GetEntrySize() => GetEntrySize(IsFormatParty);
@ -14,4 +14,4 @@ namespace PKHeX.Core
private static int GetEntrySize(bool party) => party ? PokeCrypto.SIZE_2PARTY : PokeCrypto.SIZE_2STORED;
public static int GetDataLength(PokeListType c, bool jp) => GetDataSize(c, jp, GetEntrySize(IsCapacityPartyFormat(c)));
}
}
}

View file

@ -8,7 +8,7 @@ namespace PKHeX.Core
/// </summary>
internal static class ItemConverter
{
/// <summary>Unused item ID, placeholder for item/sprite finding</summary>
/// <summary>Unused item ID, placeholder for item/sprite finding in Generations 2-4.</summary>
private const ushort NaN = 128;
/// <summary>
@ -150,7 +150,7 @@ namespace PKHeX.Core
};
/// <summary>
/// Converts a Gen1 Item to Gen2 Item.
/// Converts a Gen1 <see cref="PK1.Catch_Rate"/> value to Gen2 Item.
/// </summary>
/// <param name="value">Gen1 Item</param>
/// <returns>Gen2 Item</returns>

View file

@ -57,7 +57,7 @@ namespace PKHeX.Core
#endregion
#region Poketch
public int PoketchStart { get; protected set; }
protected int PoketchStart { private get; set; }
private byte PoketchPacked { get => General[PoketchStart]; set => General[PoketchStart] = value; }
public bool PoketchEnabled { get => (PoketchPacked & 1) != 0; set => PoketchPacked = (byte)(value ? (PoketchPacked | 1) : (PoketchPacked & ~1)); }

View file

@ -4,21 +4,38 @@ namespace PKHeX.Core
{
public sealed class InventoryItem
{
/// <summary> Item ID </summary>
public int Index;
/// <summary> Quantity </summary>
public int Count;
/// <summary> Indicates if the item is "NEW"ly obtained and not yet viewed. </summary>
public bool New;
/// <summary> Indicates if the item should be shown in the Free Space pouch instead (Generation 5). </summary>
public bool FreeSpace;
public int Index, Count;
/// <summary> Creates a copy of the object. </summary>
public InventoryItem Clone() => (InventoryItem) MemberwiseClone();
// Check Pouch Compatibility
public bool Valid(IList<ushort> LegalItems, int MaxItemID, bool HaX = false)
/// <summary>
/// Checks if the item is compatible with a pouch.
/// </summary>
/// <param name="legal">Legal Item IDs for the pouch</param>
/// <param name="maxItemID">Max item ID that exists in the game</param>
/// <param name="HaX">Bend the rules for cheaters?</param>
public bool IsValid(IList<ushort> legal, int maxItemID, bool HaX = false)
{
if (Index == 0)
return true;
if ((uint) Index > MaxItemID)
if ((uint) Index > maxItemID)
return false;
return HaX || LegalItems.Contains((ushort)Index);
return HaX || legal.Contains((ushort)Index);
}
/// <summary>
/// Resets all data in the object back to zero.
/// </summary>
public void Clear()
{
Index = Count = 0;

View file

@ -4,17 +4,31 @@ using System.Linq;
namespace PKHeX.Core
{
/// <summary>
/// Represents the data in a pouch pocket containing items of a similar type group.
/// </summary>
public abstract class InventoryPouch
{
/// <inheritdoc cref="InventoryType"/>
public readonly InventoryType Type;
/// <summary> Valid item IDs that may be stored in the pouch. </summary>
public readonly ushort[] LegalItems;
/// <summary> Max quantity for a given item that can be stored in the pouch. </summary>
public readonly int MaxCount;
/// <summary> Count of item slots occupied in the pouch. </summary>
public int Count => Items.Count(it => it.Count > 0);
/// <summary> Checks if the player may run out of bag space when there are too many unique items to fit into the pouch. </summary>
public bool IsCramped => LegalItems.Length > Items.Length;
public InventoryItem[] Items;
/// <summary> Offset the items were read from. </summary>
protected readonly int Offset;
/// <summary> Size of the backing byte array that represents the pouch. </summary>
protected readonly int PouchDataSize;
protected InventoryPouch(InventoryType type, ushort[] legal, int maxCount, int offset, int size = -1)
@ -27,10 +41,15 @@ namespace PKHeX.Core
PouchDataSize = size > -1 ? size : legal.Length;
}
public abstract void GetPouch(byte[] Data);
public abstract void SetPouch(byte[] Data);
/// <summary> Reads the pouch from the backing <see cref="data"/>. </summary>
public abstract void GetPouch(byte[] data);
/// <summary> Writes the pouch to the backing <see cref="data"/>. </summary>
public abstract void SetPouch(byte[] data);
/// <summary> Orders the <see cref="Items"/> based on <see cref="InventoryItem.Count"/> </summary>
public void SortByCount(bool reverse = false) => Array.Sort(Items, (x, y) => Compare(x.Count, y.Count, reverse));
/// <summary> Orders the <see cref="Items"/> based on <see cref="InventoryItem.Index"/> </summary>
public void SortByIndex(bool reverse = false) => Array.Sort(Items, (x, y) => Compare(x.Index, y.Index, reverse));
public void SortByName(string[] names, bool reverse = false) => Array.Sort(Items, (x, y) => Compare(x.Index, y.Index, names, reverse));
public void SortByEmpty() => Array.Sort(Items, (x, y) => (x.Count == 0).CompareTo(y.Count == 0));
@ -57,18 +76,26 @@ namespace PKHeX.Core
: i1.CompareTo(i2);
}
public void Sanitize(int MaxItemID, bool HaX = false)
/// <summary>
/// Clears invalid items and clamps any item quantity that is out of range.
/// </summary>
/// <param name="maxItemID">Max item ID that exists in the game</param>
/// <param name="HaX">Allow maximum-but-illegal quantities.</param>
public void Sanitize(int maxItemID, bool HaX = false)
{
int ctr = 0;
for (int i = 0; i < Items.Length; i++)
{
if (Items[i].Valid(LegalItems, MaxItemID, HaX))
if (Items[i].IsValid(LegalItems, maxItemID, HaX))
Items[ctr++] = Items[i];
}
while (ctr < Items.Length)
Items[ctr++] = new InventoryItem();
Items[ctr++].Clear();
}
/// <summary>
/// Clears all item slots with a quantity of zero and shifts any subsequent item slot up.
/// </summary>
public void ClearCount0()
{
int ctr = 0;
@ -78,39 +105,57 @@ namespace PKHeX.Core
Items[ctr++] = Items[i];
}
while (ctr < Items.Length)
Items[ctr++] = new InventoryItem();
Items[ctr++].Clear();
}
/// <summary>
/// Clears all items in the pouch.
/// </summary>
public void RemoveAll()
{
foreach (var item in Items)
item.Clear();
}
/// <summary>
/// Clears all items in the pouch that match the criteria to delete.
/// </summary>
public void RemoveAll(Func<InventoryItem, bool> deleteCriteria)
{
foreach (var item in Items.Where(deleteCriteria))
item.Clear();
}
/// <summary>
/// Clears all items in the pouch that match the criteria to delete, considering index within the pouch.
/// </summary>
public void RemoveAll(Func<InventoryItem, int, bool> deleteCriteria)
{
foreach (var item in Items.Where(deleteCriteria))
item.Clear();
}
/// <summary>
/// Changes all the item quantities of present items to the specified <see cref="value"/>.
/// </summary>
public void ModifyAllCount(int value)
{
foreach (var item in Items.Where(z => z.Count != 0))
item.Count = value;
}
/// <summary>
/// Changes all the item quantities of items that match the criteria to the specified <see cref="value"/>.
/// </summary>
public void ModifyAllCount(int value, Func<InventoryItem, bool> modifyCriteria)
{
foreach (var item in Items.Where(z => z.Count != 0).Where(modifyCriteria))
item.Count = value;
}
/// <summary>
/// Changes all the item quantities of items that match the criteria to the specified <see cref="value"/>, considering index within the pouch.
/// </summary>
public void ModifyAllCount(int value, Func<InventoryItem, int, bool> modifyCriteria)
{
foreach (var item in Items.Where(z => z.Count != 0).Where(modifyCriteria))
@ -154,16 +199,15 @@ namespace PKHeX.Core
var itemEnd = Math.Min(Items.Length, newItems.Count);
for (int i = 0; i < itemEnd; i++)
{
var item = Items[i] = new InventoryItem
{
Index = newItems[i],
Count = count,
New = true,
};
var item = Items[i] = new InventoryItem {Index = newItems[i]};
var match = Array.Find(current, z => z.Index == newItems[i]);
if (match == null)
{
item.Count = count;
item.New = true;
continue;
}
// load old values
item.Count = Math.Max(item.Count, match.Count);
@ -214,17 +258,17 @@ namespace PKHeX.Core
public static class InventoryPouchExtensions
{
public static IReadOnlyList<InventoryPouch> LoadAll(this IReadOnlyList<InventoryPouch> value, byte[] Data)
public static IReadOnlyList<InventoryPouch> LoadAll(this IReadOnlyList<InventoryPouch> value, byte[] data)
{
foreach (var p in value)
p.GetPouch(Data);
p.GetPouch(data);
return value;
}
public static void SaveAll(this IReadOnlyList<InventoryPouch> value, byte[] Data)
public static void SaveAll(this IReadOnlyList<InventoryPouch> value, byte[] data)
{
foreach (var p in value)
p.SetPouch(Data);
p.SetPouch(data);
}
}
}
}

View file

@ -11,29 +11,29 @@ namespace PKHeX.Core
{
}
public override void GetPouch(byte[] Data)
public override void GetPouch(byte[] data)
{
var items = new InventoryItem[PouchDataSize];
for (int i = 0; i<items.Length; i++)
{
items[i] = new InventoryItem
{
Index = BitConverter.ToUInt16(Data, Offset + (i* 4)),
Count = BitConverter.ToUInt16(Data, Offset + (i* 4) + 2) ^ (ushort) SecurityKey
Index = BitConverter.ToUInt16(data, Offset + (i* 4)),
Count = BitConverter.ToUInt16(data, Offset + (i* 4) + 2) ^ (ushort) SecurityKey
};
}
Items = items;
}
public override void SetPouch(byte[] Data)
public override void SetPouch(byte[] data)
{
if (Items.Length != PouchDataSize)
throw new ArgumentException("Item array length does not match original pouch size.");
for (int i = 0; i<Items.Length; i++)
{
BitConverter.GetBytes((ushort) Items[i].Index).CopyTo(Data, Offset + (i* 4));
BitConverter.GetBytes((ushort)((ushort) Items[i].Count ^ (ushort) SecurityKey)).CopyTo(Data, Offset + (i* 4) + 2);
BitConverter.GetBytes((ushort) Items[i].Index).CopyTo(data, Offset + (i* 4));
BitConverter.GetBytes((ushort)((ushort) Items[i].Count ^ (ushort) SecurityKey)).CopyTo(data, Offset + (i* 4) + 2);
}
}
}

View file

@ -9,29 +9,29 @@ namespace PKHeX.Core
{
}
public override void GetPouch(byte[] Data)
public override void GetPouch(byte[] data)
{
var items = new InventoryItem[PouchDataSize];
for (int i = 0; i < items.Length; i++)
{
items[i] = new InventoryItem
{
Index = BigEndian.ToUInt16(Data, Offset + (i * 4)),
Count = BigEndian.ToUInt16(Data, Offset + (i * 4) + 2)
Index = BigEndian.ToUInt16(data, Offset + (i * 4)),
Count = BigEndian.ToUInt16(data, Offset + (i * 4) + 2)
};
}
Items = items;
}
public override void SetPouch(byte[] Data)
public override void SetPouch(byte[] data)
{
if (Items.Length != PouchDataSize)
throw new ArgumentException("Item array length does not match original pouch size.");
for (int i = 0; i < Items.Length; i++)
{
BigEndian.GetBytes((ushort)Items[i].Index).CopyTo(Data, Offset + (i * 4));
BigEndian.GetBytes((ushort)Items[i].Count).CopyTo(Data, Offset + (i * 4) + 2);
BigEndian.GetBytes((ushort)Items[i].Index).CopyTo(data, Offset + (i * 4));
BigEndian.GetBytes((ushort)Items[i].Count).CopyTo(data, Offset + (i * 4) + 2);
}
}
}

View file

@ -16,29 +16,29 @@ namespace PKHeX.Core
// u16 id
// u16 count
public override void GetPouch(byte[] Data)
public override void GetPouch(byte[] data)
{
var items = new InventoryItem[PouchDataSize];
for (int i = 0; i < items.Length; i++)
{
items[i] = new InventoryItem
{
Index = BitConverter.ToUInt16(Data, Offset + (i * 4)),
Count = BitConverter.ToUInt16(Data, Offset + (i * 4) + 2)
Index = BitConverter.ToUInt16(data, Offset + (i * 4)),
Count = BitConverter.ToUInt16(data, Offset + (i * 4) + 2)
};
}
Items = items;
}
public override void SetPouch(byte[] Data)
public override void SetPouch(byte[] data)
{
if (Items.Length != PouchDataSize)
throw new ArgumentException("Item array length does not match original pouch size.");
for (int i = 0; i < Items.Length; i++)
{
BitConverter.GetBytes((ushort)Items[i].Index).CopyTo(Data, Offset + (i * 4));
BitConverter.GetBytes((ushort)Items[i].Count).CopyTo(Data, Offset + (i * 4) + 2);
BitConverter.GetBytes((ushort)Items[i].Index).CopyTo(data, Offset + (i * 4));
BitConverter.GetBytes((ushort)Items[i].Count).CopyTo(data, Offset + (i * 4) + 2);
}
}
}

View file

@ -14,7 +14,7 @@ namespace PKHeX.Core
public bool SetNew { get; set; } = false;
private InventoryItem[] OriginalItems;
public override void GetPouch(byte[] Data)
public override void GetPouch(byte[] data)
{
var items = new InventoryItem[PouchDataSize];
for (int i = 0; i < items.Length; i++)
@ -24,7 +24,7 @@ namespace PKHeX.Core
// 10bit freespace index
// 1 bit new flag
// 1 bit reserved
uint val = BitConverter.ToUInt32(Data, Offset + (i * 4));
uint val = BitConverter.ToUInt32(data, Offset + (i * 4));
items[i] = new InventoryItem
{
Index = (int)(val & 0x3FF),
@ -37,7 +37,7 @@ namespace PKHeX.Core
OriginalItems = Items.Select(i => i.Clone()).ToArray();
}
public override void SetPouch(byte[] Data)
public override void SetPouch(byte[] data)
{
if (Items.Length != PouchDataSize)
throw new ArgumentException("Item array length does not match original pouch size.");
@ -54,7 +54,7 @@ namespace PKHeX.Core
val |= 0x40000000;
if (Items[i].FreeSpace)
val |= 0x100000;
BitConverter.GetBytes(val).CopyTo(Data, Offset + (i * 4));
BitConverter.GetBytes(val).CopyTo(data, Offset + (i * 4));
}
}
}

View file

@ -16,19 +16,19 @@ namespace PKHeX.Core
public bool SetNew { get; set; }
private InventoryItem[] OriginalItems = Array.Empty<InventoryItem>();
public override void GetPouch(byte[] Data)
public override void GetPouch(byte[] data)
{
var items = new InventoryItem[PouchDataSize];
for (int i = 0; i < items.Length; i++)
{
uint val = BitConverter.ToUInt32(Data, Offset + (i * 4));
uint val = BitConverter.ToUInt32(data, Offset + (i * 4));
items[i] = GetItem(val);
}
Items = items;
OriginalItems = Items.Select(i => i.Clone()).ToArray();
}
public override void SetPouch(byte[] Data)
public override void SetPouch(byte[] data)
{
if (Items.Length != PouchDataSize)
throw new ArgumentException("Item array length does not match original pouch size.");
@ -36,7 +36,7 @@ namespace PKHeX.Core
for (int i = 0; i < Items.Length; i++)
{
uint val = SetItem(Items[i]);
BitConverter.GetBytes(val).CopyTo(Data, Offset + (i * 4));
BitConverter.GetBytes(val).CopyTo(data, Offset + (i * 4));
}
}

View file

@ -16,19 +16,19 @@ namespace PKHeX.Core
public bool SetNew { get; set; }
private InventoryItem[] OriginalItems = Array.Empty<InventoryItem>();
public override void GetPouch(byte[] Data)
public override void GetPouch(byte[] data)
{
var items = new InventoryItem[PouchDataSize];
for (int i = 0; i < items.Length; i++)
{
uint val = BitConverter.ToUInt32(Data, Offset + (i * 4));
uint val = BitConverter.ToUInt32(data, Offset + (i * 4));
items[i] = GetItem(val);
}
Items = items;
OriginalItems = Items.Select(i => i.Clone()).ToArray();
}
public override void SetPouch(byte[] Data)
public override void SetPouch(byte[] data)
{
if (Items.Length != PouchDataSize)
throw new ArgumentException("Item array length does not match original pouch size.");
@ -36,7 +36,7 @@ namespace PKHeX.Core
for (int i = 0; i < Items.Length; i++)
{
uint val = SetItem(Items[i]);
BitConverter.GetBytes(val).CopyTo(Data, Offset + (i * 4));
BitConverter.GetBytes(val).CopyTo(data, Offset + (i * 4));
}
}

View file

@ -9,7 +9,7 @@ namespace PKHeX.Core
{
}
public override void GetPouch(byte[] Data)
public override void GetPouch(byte[] data)
{
var items = new InventoryItem[PouchDataSize];
if (Type == InventoryType.TMHMs)
@ -17,12 +17,12 @@ namespace PKHeX.Core
int slot = 0;
for (int i = 0; i < items.Length; i++)
{
if (Data[Offset + i] != 0)
if (data[Offset + i] != 0)
{
items[slot++] = new InventoryItem
{
Index = LegalItems[i],
Count = Data[Offset + i]
Count = data[Offset + i]
};
}
}
@ -37,7 +37,7 @@ namespace PKHeX.Core
}
else
{
int numStored = Data[Offset];
int numStored = data[Offset];
if (numStored > PouchDataSize) // uninitialized yellow (0xFF), sanity check for out-of-bounds values
numStored = 0;
for (int i = 0; i < numStored; i++)
@ -45,9 +45,9 @@ namespace PKHeX.Core
items[i] = Type switch
{
InventoryType.KeyItems =>
new InventoryItem {Index = Data[Offset + i + 1], Count = 1},
new InventoryItem {Index = data[Offset + i + 1], Count = 1},
_ =>
new InventoryItem {Index = Data[Offset + (i * 2) + 1], Count = Data[Offset + (i * 2) + 2]}
new InventoryItem {Index = data[Offset + (i * 2) + 1], Count = data[Offset + (i * 2) + 2]}
};
}
for (int i = numStored; i < items.Length; i++)
@ -62,7 +62,7 @@ namespace PKHeX.Core
Items = items;
}
public override void SetPouch(byte[] Data)
public override void SetPouch(byte[] data)
{
if (Items.Length != PouchDataSize)
throw new ArgumentException("Item array length does not match original pouch size.");
@ -77,25 +77,25 @@ namespace PKHeX.Core
int index = Array.FindIndex(LegalItems, it => t.Index == it);
if (index < 0) // enforce correct pouch
continue;
Data[Offset + index] = (byte)t.Count;
data[Offset + index] = (byte)t.Count;
}
break;
case InventoryType.KeyItems:
for (int i = 0; i < Items.Length; i++)
{
Data[Offset + i + 1] = (byte)Items[i].Index;
data[Offset + i + 1] = (byte)Items[i].Index;
}
Data[Offset] = (byte)Count;
Data[Offset + 1 + Count] = 0xFF;
data[Offset] = (byte)Count;
data[Offset + 1 + Count] = 0xFF;
break;
default:
for (int i = 0; i < Items.Length; i++)
{
Data[Offset + (i * 2) + 1] = (byte)Items[i].Index;
Data[Offset + (i * 2) + 2] = (byte)Items[i].Count;
data[Offset + (i * 2) + 1] = (byte)Items[i].Index;
data[Offset + (i * 2) + 2] = (byte)Items[i].Count;
}
Data[Offset] = (byte)Count;
Data[Offset + 1 + (2 * Count)] = 0xFF;
data[Offset] = (byte)Count;
data[Offset + 1 + (2 * Count)] = 0xFF;
break;
}
}

View file

@ -3,7 +3,7 @@ namespace PKHeX.Core
/// <summary>
/// Type of items the <see cref="InventoryPouch"/> contains.
/// </summary>
/// <remarks>Used by the Inventory Editor as the index for sprite lookup</remarks>
/// <remarks>Used by the Inventory Editor as the index for sprite lookup.</remarks>
public enum InventoryType
{
Items,

View file

@ -3,6 +3,9 @@ using System.Linq;
namespace PKHeX.Core
{
/// <summary>
/// Base class for Pokédex logic operations.
/// </summary>
public abstract class ZukanBase
{
protected readonly SaveFile SAV;
@ -14,18 +17,25 @@ namespace PKHeX.Core
PokeDex = dex;
}
#region Overall Info
/// <summary> Count of unique Species Seen </summary>
public int SeenCount => Enumerable.Range(1, SAV.MaxSpeciesID).Count(GetSeen);
/// <summary> Count of unique Species Caught (Owned) </summary>
public int CaughtCount => Enumerable.Range(1, SAV.MaxSpeciesID).Count(GetCaught);
public decimal PercentSeen => (decimal)SeenCount / SAV.MaxSpeciesID;
public decimal PercentCaught => (decimal)CaughtCount / SAV.MaxSpeciesID;
#endregion
/// <summary> Gets if the Species has been Seen by the player. </summary>
public abstract bool GetSeen(int species);
/// <summary> Gets if the Species has been Caught (Owned) by the player. </summary>
public abstract bool GetCaught(int species);
/// <summary> Adds the Pokémon's information to the Pokédex. </summary>
public abstract void SetDex(PKM pkm);
// Bulk Manipulation
#region Overall Manipulation
public abstract void SeenNone();
public abstract void CaughtNone();
@ -36,8 +46,12 @@ namespace PKHeX.Core
public abstract void SetDexEntryAll(int species, bool shinyToo = false);
public abstract void ClearDexEntryAll(int species);
#endregion
}
/// <summary>
/// Base class for Pokédex operations, exposing the shared structure features used by Generations 5, 6, and 7.
/// </summary>
public abstract class Zukan : ZukanBase
{
protected readonly int PokeDexLanguageFlags;

View file

@ -2,6 +2,9 @@
namespace PKHeX.Core
{
/// <summary>
/// Pokédex structure used for Generation 5 games.
/// </summary>
public sealed class Zukan5 : Zukan
{
protected override int OFS_SEEN => OFS_CAUGHT + BitSeenSize;

View file

@ -3,6 +3,9 @@ using System.Diagnostics;
namespace PKHeX.Core
{
/// <summary>
/// Pokédex structure used for Generation 6 games.
/// </summary>
public abstract class Zukan6 : Zukan
{
protected override int OFS_SEEN => OFS_CAUGHT + BitSeenSize;
@ -178,6 +181,9 @@ namespace PKHeX.Core
}
}
/// <summary>
/// Pokédex structure used for <see cref="GameVersion.ORAS"/>.
/// </summary>
public sealed class Zukan6AO : Zukan6
{
public Zukan6AO(SAV6AO sav, int dex, int langflag) : base(sav, dex, langflag)
@ -206,6 +212,9 @@ namespace PKHeX.Core
}
}
/// <summary>
/// Pokédex structure used for <see cref="GameVersion.XY"/>.
/// </summary>
public sealed class Zukan6XY : Zukan6
{
public Zukan6XY(SAV6XY sav, int dex, int langflag) : base(sav, dex, langflag)

View file

@ -5,8 +5,8 @@ using System.Diagnostics;
namespace PKHeX.Core
{
/// <summary>
/// Generation 7 Dex manipulator
/// </summary>
/// Pokédex structure used for Generation 7 games.
/// </summary>>
public class Zukan7 : Zukan
{
private const int MAGIC = 0x2F120F17;

View file

@ -3,8 +3,8 @@ using System;
namespace PKHeX.Core
{
/// <summary>
/// Beluga specific Dex manipulator, slightly modified from Gen7.
/// </summary>
/// Pokédex structure used for <see cref="GameVersion.GG"/> games, slightly modified from <see cref="Zukan7"/>.
/// </summary>>
public sealed class Zukan7b : Zukan7
{
public Zukan7b(SAV7b sav, int dex, int langflag) : base(sav, dex, langflag)

View file

@ -3,12 +3,18 @@ using System.Collections.Generic;
namespace PKHeX.Core
{
// I wish I could replace this with raw pointers via Span :)
/// <summary>
/// Pokédex structure used for <see cref="GameVersion.SWSH"/>.
/// </summary>>
public sealed class Zukan8 : ZukanBase
{
private readonly SCBlock Galar;
private readonly SCBlock Rigel1;
private readonly SCBlock Rigel2;
/// <summary>
/// Reverses a Species into the component <see cref="Zukan8Index"/> information.
/// </summary>
public readonly IReadOnlyDictionary<int, Zukan8Index> DexLookup;
public Zukan8(SAV8SWSH sav, SCBlock galar, SCBlock rigel1, SCBlock rigel2) : base(sav, 0)
@ -20,6 +26,9 @@ namespace PKHeX.Core
DexLookup = GetDexLookup(PersonalTable.SWSH, revision);
}
/// <summary>
/// Checks how much DLC patches have been installed by detecting if DLC blocks are present.
/// </summary>
public int GetRevision()
{
if (Rigel1.Data.Length == 0)
@ -118,6 +127,7 @@ namespace PKHeX.Core
_ => lang - 1,
};
#if DEBUG
public IList<string> GetEntryNames(IReadOnlyList<string> speciesNames)
{
var dex = new List<string>();
@ -131,6 +141,7 @@ namespace PKHeX.Core
dex.Sort();
return dex;
}
#endif
#region Structure
@ -462,16 +473,19 @@ namespace PKHeX.Core
bool owned = GetCaught(species);
var g = pkm.Gender == 1 ? 1 : 0;
var gender = pkm.Gender;
bool shiny = pkm.IsShiny;
var s = shiny ? 2 : 0;
int form = pkm.Form;
var language = pkm.Language;
var g = gender & 1;
var s = shiny ? 2 : 0;
if (species == (int)Species.Alcremie)
{
form *= 7;
form += (int)((PK8)pkm).FormArgument; // alteration byte
}
else if (species == (int) Species.Eternatus && pkm.Form == 1)
else if (species == (int) Species.Eternatus && form == 1)
{
form = 0;
SetSeenRegion(species, 63, g | s);
@ -479,7 +493,7 @@ namespace PKHeX.Core
SetSeenRegion(species, form, g | s);
SetCaught(species);
SetIsLanguageObtained(species, pkm.Language);
SetIsLanguageObtained(species, language);
if (!owned)
{
SetFormDisplayed(species, (byte)form);
@ -706,10 +720,16 @@ namespace PKHeX.Core
#endregion
}
/// <summary>
/// Indicates which <see cref="Zukan8Type"/> block will store the entry, and at what index.
/// </summary>
public readonly struct Zukan8Index
{
/// <summary> Index that the Pokédex entry is stored at. </summary>
public readonly int Index;
/// <summary> Which block stores the Pokédex entry. </summary>
public readonly Zukan8Type DexType;
public override string ToString() => $"{Index:000} - {DexType}";
public Zukan8Index(Zukan8Type dexType, int index)
@ -729,12 +749,16 @@ namespace PKHeX.Core
public int Offset => GetSavedIndex() * Zukan8.EntrySize;
private const int GalarCount = 400;
private const int Rigel1Count = 211;
private const int Rigel2Count = 2;
// expects zero based indexes
public static Zukan8Index GetFromRawIndex(int index)
private const int GalarCount = 400; // Count within Galar dex
private const int Rigel1Count = 211; // Count within Armor dex
private const int Rigel2Count = 210; // Count within Crown dex
#if DEBUG
public const int TotalCount = GalarCount + Rigel1Count + Rigel2Count;
/// <summary>
/// Gets the <see cref="Zukan8Index"/> from the absolute (overall) dex index. Don't use this method unless you're analyzing things.
/// </summary>
/// <param name="index">Unique Pokédex index (incremental). Should be 0-indexed.</param>
public static Zukan8Index GetFromAbsoluteIndex(int index)
{
if (index < 0)
return new Zukan8Index();
@ -752,14 +776,9 @@ namespace PKHeX.Core
throw new ArgumentOutOfRangeException(nameof(index));
}
#endif
public string DexPrefix => DexType switch
{
Zukan8Type.Galar => "O0",
Zukan8Type.Armor => "R1",
Zukan8Type.Crown => "R2",
_ => throw new ArgumentOutOfRangeException()
};
public string DexPrefix => DexType.GetZukanTypeInternalPrefix();
public int AbsoluteIndex => DexType switch
{
@ -802,4 +821,15 @@ namespace PKHeX.Core
Armor,
Crown,
}
public static class Zukan8TypeExtensions
{
public static string GetZukanTypeInternalPrefix(this Zukan8Type type) => type switch
{
Zukan8Type.Galar => "O0",
Zukan8Type.Armor => "R1",
Zukan8Type.Crown => "R2",
_ => throw new ArgumentOutOfRangeException(nameof(type))
};
}
}

View file

@ -2,7 +2,6 @@
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
namespace PKHeX.Core
{
@ -36,27 +35,5 @@ namespace PKHeX.Core
var httpWebResponse = httpWebRequest.GetResponse();
return httpWebResponse.GetResponseStream();
}
private static readonly Regex LatestGitTagRegex = new("\\\"tag_name\"\\s*\\:\\s*\\\"([0-9]+\\.[0-9]+\\.[0-9]+)\\\""); // Match `"tag_name": "18.12.02"`. Group 1 is `18.12.02`
/// <summary>
/// Gets the latest version of PKHeX according to the Github API
/// </summary>
/// <returns>A version representing the latest available version of PKHeX, or null if the latest version could not be determined</returns>
public static Version? GetLatestPKHeXVersion()
{
const string apiEndpoint = "https://api.github.com/repos/kwsch/pkhex/releases/latest";
var responseJson = GetStringFromURL(apiEndpoint);
if (string.IsNullOrEmpty(responseJson))
return null;
// Using a regex to get the tag to avoid importing an entire JSON parsing library
var tagMatch = LatestGitTagRegex.Match(responseJson);
if (!tagMatch.Success)
return null;
var tagString = tagMatch.Groups[1].Value;
return !Version.TryParse(tagString, out var latestVersion) ? null : latestVersion;
}
}
}

View file

@ -0,0 +1,30 @@
using System;
using System.Text.RegularExpressions;
namespace PKHeX.Core
{
public static class UpdateUtil
{
private static readonly Regex LatestGitTagRegex = new("\\\"tag_name\"\\s*\\:\\s*\\\"([0-9]+\\.[0-9]+\\.[0-9]+)\\\""); // Match `"tag_name": "18.12.02"`. Group 1 is `18.12.02`
/// <summary>
/// Gets the latest version of PKHeX according to the Github API
/// </summary>
/// <returns>A version representing the latest available version of PKHeX, or null if the latest version could not be determined</returns>
public static Version? GetLatestPKHeXVersion()
{
const string apiEndpoint = "https://api.github.com/repos/kwsch/pkhex/releases/latest";
var responseJson = NetUtil.GetStringFromURL(apiEndpoint);
if (string.IsNullOrEmpty(responseJson))
return null;
// Using a regex to get the tag to avoid importing an entire JSON parsing library
var tagMatch = LatestGitTagRegex.Match(responseJson);
if (!tagMatch.Success)
return null;
var tagString = tagMatch.Groups[1].Value;
return !Version.TryParse(tagString, out var latestVersion) ? null : latestVersion;
}
}
}

View file

@ -236,7 +236,7 @@ namespace PKHeX.WinForms
{
Version? latestVersion;
// User might not be connected to the internet or with a flaky connection.
try { latestVersion = NetUtil.GetLatestPKHeXVersion(); }
try { latestVersion = UpdateUtil.GetLatestPKHeXVersion(); }
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types