Minor clean

StringBuilder.Append has some fancy interpolation handling in the latest NET8 so it's more clean than multiple append calls.
This commit is contained in:
Kurt 2024-06-15 00:57:44 -05:00
parent 0ffb256052
commit f6bcc8a216
29 changed files with 216 additions and 221 deletions

View File

@ -1,6 +1,5 @@
using System;
using System.Buffers;
using System.Text;
namespace PKHeX.Core;
@ -55,10 +54,10 @@ public static string GetMessage(PKM pk)
/// <returns>QR Message</returns>
public static string GetMessage(ReadOnlySpan<byte> payload)
{
var sb = new StringBuilder(payload.Length);
foreach (var b in payload)
sb.Append((char)b);
return sb.ToString();
Span<char> result = stackalloc char[payload.Length];
for (int i = 0; i < payload.Length; i++)
result[i] = (char)payload[i];
return new string(result);
}
/// <summary>

View File

@ -25,7 +25,7 @@ private void Summarize(StringBuilder sb, ReadOnlySpan<char> localizedMethod)
sb.Append(Environment).Append('-');
sb.Append(localizedMethod);
if (Method is LevelUp)
sb.Append(" @ lv").Append(Argument);
sb.Append($" @ lv{Argument}");
}
private string GetLocalizedMethod() => Method switch

View File

@ -52,10 +52,9 @@ public override string ToString()
sb.Append(" (Shadow)");
if (Seen)
sb.Append(" [Seen]");
sb.Append(" - ");
sb.Append("Nature: ").Append((Nature)Nature);
sb.Append($" - Nature: {(Nature)Nature}");
if (Gender != 2)
sb.Append(", ").Append("Gender: ").Append(Gender);
sb.Append($", Gender: {Gender}");
return sb.ToString();
}
#endif

View File

@ -124,10 +124,6 @@ public static bool SetFromIVsK<T>(this T enc, PK4 pk, PersonalInfo4 pi, Encounte
public static uint GetPIDRegular(uint a, uint b) => b << 16 | a;
private static void SetPIDIVSequential(PK4 pk, uint pid, uint rand)
{
}
private static (uint iv1, uint iv2) GetCombinedIVs(EncounterCriteria criteria)
{
uint iv1 = (uint)criteria.IV_HP | (uint)criteria.IV_ATK << 5 | (uint)criteria.IV_DEF << 10;

View File

@ -352,4 +352,3 @@ public enum GiftSubType4 : byte
Accessory = 2,
Backdrop = 3,
}

View File

@ -705,7 +705,7 @@ private bool IsMatchLocation(PKM pk)
return IsMatchLocationExact(pk) || IsMatchLocationRemapped(pk);
}
private bool IsMatchLocationExact(PKM pk) => pk.MetLocation == this.Location;
private bool IsMatchLocationExact(PKM pk) => pk.MetLocation == Location;
private bool IsMatchLocationRemapped(PKM pk)
{
@ -713,7 +713,7 @@ private bool IsMatchLocationRemapped(PKM pk)
var version = pk.Version;
if (pk.Context == EntityContext.Gen8)
return LocationsHOME.IsValidMetBDSP(met, version);
return LocationsHOME.GetMetSWSH(this.Location, version) == met;
return LocationsHOME.GetMetSWSH(Location, version) == met;
}
protected override bool IsMatchDeferred(PKM pk) => false;

View File

@ -191,13 +191,13 @@ public static class StringFont8b
'\uFB30', '\uFB31', '\uFB32', '\uFB33', '\uFB34', '\uFB35', '\uFB36', '\uFB38', '\uFB39', '\uFB3A', '\uFB3B', '\uFB3C', '\uFB3E',
'\uFB40', '\uFB41', '\uFB43', '\uFB44', '\uFB46', '\uFB47', '\uFB48', '\uFB49', '\uFB4A', '\uFB4B', '\uFB4C', '\uFB4D', '\uFB4E', '\uFB4F',
'\uFE20', '\uFE21', '\uFE22', '\uFE23',
'\uFFFC'
'\uFFFC',
];
public static ReadOnlySpan<char> DefinedCHSExt => [
'\u0020', '\u002D', '\u003F', '\u0067', '\u00AA', '\u00B7', '\u00E9',
'\u2013', '\u2018', '\u2019', '\u201C', '\u201D', '\u201E', '\u2026', '\u20BD', '\u21D2', '\u21D4', '\u2200', '\u2282', '\u2283',
'\u25A0', '\u25BC', '\u25BD', '\u25CF', '\u2605', '\u2661', '\u2665', '\u266A', '\u266D',
'\u300A', '\u300B', '\u300C', '\u300D', '\u300E', '\u300F', '\u3010', '\u3011', '\u30FB', '\uFF08', '\uFF09', '\uFF65'
'\u300A', '\u300B', '\u300C', '\u300D', '\u300E', '\u300F', '\u3010', '\u3011', '\u30FB', '\uFF08', '\uFF09', '\uFF65',
];
}

View File

@ -105,9 +105,8 @@ public static bool IsFromTrainerEgg(this ITrainerInfo tr, PKM pk)
if (tr.Version != pk.Version)
{
// PK9 does not store version for Picnic eggs.
if (pk is PK9 { Version: 0 }) { }
else { return false; }
if (!IsVersionlessState(pk))
return false;
}
Span<char> ot = stackalloc char[pk.MaxStringLengthTrainer];
@ -119,6 +118,14 @@ public static bool IsFromTrainerEgg(this ITrainerInfo tr, PKM pk)
return true;
}
private static bool IsVersionlessState(PKM pk)
{
// PK9 does not store version for Picnic eggs.
if (pk is PK9 { Version: 0 }) // IsEgg is already true for all calls
return true;
return false;
}
private static bool IsMatchVersion(ITrainerInfo tr, PKM pk)
{
if (tr.Version == pk.Version)

View File

@ -119,15 +119,15 @@ public static string GetBlockFileNameWithoutExtension(SCBlock block)
public static string GetBlockSummary(SCBlock b)
{
var sb = new StringBuilder(64);
sb.Append("Key: ").AppendFormat("{0:X8}", b.Key).AppendLine();
sb.Append("Type: ").Append(b.Type).AppendLine();
sb.AppendLine($"Key: {b.Key:X8}");
sb.AppendLine($"Type: {b.Type}");
if (b.Data.Length != 0)
sb.Append("Length: ").AppendFormat("{0:X8}", b.Data.Length).AppendLine();
sb.AppendLine($"Length: {b.Data.Length:X8}");
if (b.SubType != 0)
sb.Append("SubType: ").Append(b.SubType).AppendLine();
sb.AppendLine($"SubType: {b.SubType}");
else if (b.HasValue())
sb.Append("Value: ").Append(b.GetValue()).AppendLine();
sb.AppendLine($"Value: {b.GetValue()}");
return sb.ToString();
}

View File

@ -243,7 +243,6 @@ private int GetActiveExtraBlock(BlockInfo4 block)
protected int OFS_Record = int.MinValue;
public Record4 Records => new(this, Data.AsMemory(OFS_Record, Record4.GetSize(this)));
// Storage
public override int PartyCount
{

View File

@ -16,7 +16,7 @@ public sealed class SAV5B2W2 : SAV5, ISaveBlock5B2W2
public SaveBlockAccessor5B2W2 Blocks { get; }
protected override SAV5B2W2 CloneInternal() => new((byte[]) Data.Clone());
public override int MaxItemID => Legal.MaxItemID_5_B2W2;
public override IReadOnlyList<BlockInfo> AllBlocks => Blocks.BlockInfo;
public override MyItem Items => Blocks.Items;
public override Zukan5 Zukan => Blocks.Zukan;

View File

@ -136,7 +136,7 @@ public enum DecorationCategory3 : byte
Mat,
Poster,
Doll,
Cushion
Cushion,
}
public static class DecorationInfo

View File

@ -45,7 +45,7 @@ private string GetSummary(StringBuilder sb, IBasicStrings g)
{
sb.Append($"{Species:000} - {g.Species[Species]}");
if (HeldItem != 0)
sb.Append(" @ ").Append(g.Item[HeldItem]);
sb.Append($" @ {g.Item[HeldItem]}");
sb.AppendLine();
var moveNames = g.Move;

View File

@ -17,9 +17,9 @@ public sealed class Record4(SAV4 SAV, Memory<byte> raw) : SaveBlock<SAV4>(SAV, r
{
public static int GetSize(SAV4 SAV) => SAV switch
{
SAV4DP => Record32DP * sizeof(uint) + Record16 * sizeof(ushort),
SAV4Pt => Record32Pt * sizeof(uint) + Record16 * sizeof(ushort) + 3 * sizeof(ushort),
SAV4HGSS => Record32HGSS * sizeof(uint) + Record16 * sizeof(ushort) + 3 * sizeof(ushort),
SAV4DP => (Record32DP * sizeof(uint)) +(Record16 * sizeof(ushort)),
SAV4Pt => (Record32Pt * sizeof(uint)) +(Record16 * sizeof(ushort)) + (3 * sizeof(ushort)),
SAV4HGSS => (Record32HGSS * sizeof(uint)) +(Record16 * sizeof(ushort)) + (3 * sizeof(ushort)),
_ => throw new ArgumentOutOfRangeException(nameof(SAV)),
};
@ -70,7 +70,7 @@ public ushort InitSeed
/// </remarks>
public uint CryptoSeed
{
get => (SAV is SAV4DP) ? (ushort)0 : ReadUInt32LittleEndian(Data[^4..]);
get => (SAV is SAV4DP) ? 0 : ReadUInt32LittleEndian(Data[^4..]);
set { if (SAV is not SAV4DP) WriteUInt32LittleEndian(Data[^4..], value); }
}
@ -81,7 +81,7 @@ private void EnsureDecrypted(bool state = true)
{
if (SAV is SAV4DP || IsDecrypted == state) // DP does not encrypt records
return;
if (IsDecrypted && state == false)
if (IsDecrypted && !state)
RefreshChecksum(); // refresh only on encrypt
PokeCrypto.CryptArray(CryptoData, CryptoSeed);
IsDecrypted = state;
@ -175,14 +175,14 @@ private void EnsureDecrypted(bool state = true)
public uint GetRecord32(int index)
{
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual<uint>((uint)index, (uint)Record32);
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((uint)index, (uint)Record32);
EnsureDecrypted();
return ReadUInt32LittleEndian(Record32Data[(index * 4)..]);
}
public void SetRecord32(int index, uint value)
{
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual<uint>((uint)index, (uint)Record32);
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((uint)index, (uint)Record32);
EnsureDecrypted();
WriteUInt32LittleEndian(Record32Data[(index * 4)..], Math.Min(GetMax32(index), value));
}

View File

@ -221,5 +221,5 @@ public enum MaxRaidOrigin: uint
{
Galar,
IsleOfArmor,
CrownTundra
CrownTundra,
}

View File

@ -156,5 +156,5 @@ public enum TeraRaidOrigin : uint
{
Paldea,
Kitakami,
BlueberryAcademy
BlueberryAcademy,
}

View File

@ -31,6 +31,7 @@ public interface IGeonet
/// </summary>
/// <param name="country">Country index</param>
/// <param name="subregion">Subregion index</param>
/// <param name="point">Point status</param>
void SetCountrySubregion(byte country, byte subregion, GeonetPoint point);
/// <summary>

View File

@ -60,7 +60,7 @@ public static string ConvertDateValueToString(int value, int secondsBias = -1)
value %= SecondsPerDay;
sb.Append(new TimeOnly(ticks: value * TimeSpan.TicksPerSecond).ToString("HH:mm:ss"));
if (secondsBias >= 0)
sb.Append(Environment.NewLine).Append("Date: ").Append(Epoch2000.AddSeconds(value + secondsBias));
sb.Append(Environment.NewLine).Append($"Date: {Epoch2000.AddSeconds(value + secondsBias)}");
return sb.ToString();
}

View File

@ -210,11 +210,11 @@ public static bool TryGetMemoryCard(string file, [NotNullWhen(true)] out SAV3GCM
/// <param name="data">Binary data</param>
/// <param name="pk">Output result</param>
/// <param name="ext">Format hint</param>
/// <param name="sav">Reference savefile used for PC Binary compatibility checks.</param>
/// <param name="sav">Reference save file used for PC Binary compatibility checks.</param>
/// <returns>True if file object reference is valid, false if none found.</returns>
public static bool TryGetPKM(byte[] data, [NotNullWhen(true)] out PKM? pk, ReadOnlySpan<char> ext, ITrainerInfo? sav = null)
{
if (ext == ".pgt") // size collision with pk6
if (ext.EndsWith("pgt")) // size collision with pk6
{
pk = null;
return false;

View File

@ -1,12 +1,10 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PKHeX.Core;
using static System.Buffers.Binary.BinaryPrimitives;
using static PKHeX.Core.DecorationCategory3;
namespace PKHeX.WinForms;
@ -118,7 +116,7 @@ private void ReadJoyful(IGen3Joyful j)
TB_B1.Text = Math.Min((ushort)9999, j.JoyfulBerriesInRow).ToString();
TB_B2.Text = Math.Min(99990, j.JoyfulBerriesScore).ToString();
TB_B3.Text = Math.Min((ushort)9999, j.JoyfulBerries5InRow).ToString();
TB_BerryPowder.Text = Math.Min((uint)99999, j.BerryPowder).ToString();
TB_BerryPowder.Text = Math.Min(99999u, j.BerryPowder).ToString();
}
private void SaveJoyful(IGen3Joyful j)

View File

@ -756,7 +756,7 @@ private void ReadSeals()
DGV_Seals.Columns.Add(dgvSlot);
DGV_Seals.Columns.Add(dgvCount);
var count = (int)Seal4.MAX;
const int count = (int)Seal4.MAX;
DGV_Seals.Rows.Add(count);
for (int i = 0; i < count; i++)
DGV_Seals.Rows[i].Cells[0].Value = seals[i];
@ -825,7 +825,7 @@ private void ReadAccessories()
DGV_Accessories.Columns.Add(dgvSlot);
DGV_Accessories.Columns.Add(dgvCount);
var count = AccessoryInfo.Count;
const int count = AccessoryInfo.Count;
DGV_Accessories.Rows.Add(count);
for (int i = 0; i < count; i++)
DGV_Accessories.Rows[i].Cells[0].Value = accessories[i];

View File

@ -21,7 +21,7 @@ public SAV_Raid8(SAV8SWSH sav, MaxRaidOrigin raidOrigin)
MaxRaidOrigin.Galar => SAV.RaidGalar,
MaxRaidOrigin.IsleOfArmor => SAV.RaidArmor,
MaxRaidOrigin.CrownTundra => SAV.RaidCrown,
_ => throw new ArgumentOutOfRangeException($"Raid Origin {raidOrigin} is not valid for Sword and Shield")
_ => throw new ArgumentOutOfRangeException($"Raid Origin {raidOrigin} is not valid for Sword and Shield"),
};
CB_Den.Items.AddRange(Enumerable.Range(1, Raids.CountUsed).Select(z => (object)$"Den {z:000}").ToArray());
CB_Den.SelectedIndex = 0;

View File

@ -156,7 +156,6 @@ private void GetEntry(ushort species)
if (forms[0].Length == 0)
forms[0] = GameInfo.Strings.Types[0];
this.SuspendLayout();
// Clear all CheckedListBoxes
var seen = CLB_FormSeen.Items;
var obtained = CLB_FormObtained.Items;

View File

@ -22,7 +22,7 @@ public SAV_Raid9(SAV9SV sav, TeraRaidOrigin raidOrigin)
TeraRaidOrigin.Paldea => SAV.RaidPaldea,
TeraRaidOrigin.Kitakami => SAV.RaidKitakami,
TeraRaidOrigin.BlueberryAcademy => SAV.RaidBlueberry,
_ => throw new ArgumentOutOfRangeException($"Raid Origin {raidOrigin} is not valid for Scarlet and Violet")
_ => throw new ArgumentOutOfRangeException($"Raid Origin {raidOrigin} is not valid for Scarlet and Violet"),
};
CB_Raid.Items.AddRange(Enumerable.Range(1, Raids.CountUsed).Select(z => (object)$"Raid {z:000}").ToArray());
CB_Raid.SelectedIndex = 0;

View File

@ -7,182 +7,181 @@
using PKHeX.Core;
using PKHeX.WinForms.Controls;
namespace PKHeX.WinForms
namespace PKHeX.WinForms;
public static class DevUtil
{
public static class DevUtil
public static void AddControl(ToolStripDropDownItem t)
{
public static void AddControl(ToolStripDropDownItem t)
t.DropDownItems.Add(GetTranslationUpdater());
}
private static readonly string[] Languages = ["ja", "fr", "it", "de", "es", "ko", "zh", "zh2"];
private static string DefaultLanguage => Main.CurrentLanguage;
public static bool IsUpdatingTranslations { get; private set; }
/// <summary>
/// Call this to update all translatable resources (Program Messages, Legality Text, Program GUI)
/// </summary>
private static void UpdateAll()
{
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Update translation files with current values?"))
return;
IsUpdatingTranslations = true;
DumpStringsLegality();
DumpStringsMessage();
UpdateTranslations();
IsUpdatingTranslations = false;
}
private static ToolStripMenuItem GetTranslationUpdater()
{
var ti = new ToolStripMenuItem
{
t.DropDownItems.Add(GetTranslationUpdater());
ShortcutKeys = Keys.Control | Keys.Alt | Keys.D,
Visible = false,
};
ti.Click += (_, _) => UpdateAll();
return ti;
}
private static void UpdateTranslations()
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var types = assembly.GetTypes();
// Trigger a translation then dump all.
foreach (var lang in Languages) // get all languages ready to go
_ = WinFormsTranslator.GetDictionary(lang);
WinFormsTranslator.SetUpdateMode();
WinFormsTranslator.LoadSettings<PKHeXSettings>(DefaultLanguage);
WinFormsTranslator.LoadEnums(EnumTypesToTranslate, DefaultLanguage);
WinFormsTranslator.LoadAllForms(types, LoadBanlist); // populate with every possible control
WinFormsTranslator.TranslateControls(GetExtraControls(), DefaultLanguage);
var dir = GetResourcePath("PKHeX.WinForms", "Resources", "text");
WinFormsTranslator.DumpAll(DefaultLanguage, Banlist, dir); // dump current to file
WinFormsTranslator.SetUpdateMode(false);
// Move translated files from the debug exe loc to their project location
var files = Directory.GetFiles(Application.StartupPath);
foreach (var f in files)
{
var fn = Path.GetFileName(f);
if (!fn.EndsWith(".txt"))
continue;
if (!fn.StartsWith("lang_"))
continue;
var loc = Path.Combine(dir, fn);
if (File.Exists(loc))
File.Delete(loc);
File.Move(f, loc, true);
}
private static readonly string[] Languages = ["ja", "fr", "it", "de", "es", "ko", "zh", "zh2"];
private static string DefaultLanguage => Main.CurrentLanguage;
Application.Exit();
}
public static bool IsUpdatingTranslations { get; private set; }
private static readonly Type[] EnumTypesToTranslate =
[
typeof(StatusCondition),
typeof(PokeSize),
typeof(PokeSizeDetailed),
/// <summary>
/// Call this to update all translatable resources (Program Messages, Legality Text, Program GUI)
/// </summary>
private static void UpdateAll()
typeof(PassPower5),
typeof(Funfest5Mission),
typeof(OPower6Index),
typeof(OPower6FieldType),
typeof(OPower6BattleType),
typeof(PlayerBattleStyle7),
typeof(PlayerSkinColor7),
typeof(Stamp7),
typeof(FestivalPlazaFacilityColor),
];
private static IEnumerable<Control> GetExtraControls()
{
foreach (var name in SlotList.GetEnumNames().Distinct())
yield return new Label { Name = $"{nameof(Main)}.L_{name}", Text = name };
}
private static readonly string[] LoadBanlist =
[
nameof(SplashScreen),
nameof(PokePreview),
];
private static readonly string[] Banlist =
[
"Gender=", // editor gender labels
"BTN_Shinytize", // ☆
"Hidden_", // Hidden controls
"CAL_", // calendar controls now expose Text, don't care.
".Count", // enum count
$"{nameof(Main)}.L_SizeH", // height rating
$"{nameof(Main)}.L_SizeW", // weight rating
$"{nameof(Main)}.L_SizeS", // scale rating
$"{nameof(Main)}.B_Box", // << and >> arrows
$"{nameof(Main)}.L_Characteristic=", // Characterstic (dynamic)
$"{nameof(Main)}.L_Potential", // ★☆☆☆ IV judge evaluation
$"{nameof(SAV_HoneyTree)}.L_Tree0", // dynamic, don't bother
$"{nameof(SAV_Misc3)}.BTN_Symbol", // symbols should stay as their current character
$"{nameof(SAV_GameSelect)}.L_Prompt", // prompt text (dynamic)
$"{nameof(SAV_BlockDump8)}.L_BlockName", // Block name (dynamic)
$"{nameof(SAV_PokedexResearchEditorLA)}.L_", // Dynamic label
$"{nameof(SAV_OPower)}.L_", // Dynamic label
];
private static void DumpStringsMessage() => DumpStrings(typeof(MessageStrings), false, "PKHeX.Core", "Resources", "text", "program");
private static void DumpStringsLegality() => DumpStrings(typeof(LegalityCheckStrings), true, "PKHeX.Core", "Resources", "legality", "checks");
private static void DumpStrings(Type t, bool sorted, params string[] rel)
{
var dir = GetResourcePath(rel);
DumpStrings(t, sorted, DefaultLanguage, dir);
foreach (var lang in Languages)
DumpStrings(t, sorted, lang, dir);
}
private static void DumpStrings(Type t, bool sorted, string lang, string dir)
{
LocalizationUtil.SetLocalization(t, lang);
var entries = LocalizationUtil.GetLocalization(t);
IEnumerable<string> export = entries.OrderBy(GetName); // sorted lines
if (!sorted)
export = entries;
var location = GetFileLocationInText(t.Name, dir, lang);
File.WriteAllLines(location, export);
LocalizationUtil.SetLocalization(t, DefaultLanguage);
static string GetName(string line)
{
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Update translation files with current values?"))
return;
IsUpdatingTranslations = true;
DumpStringsLegality();
DumpStringsMessage();
UpdateTranslations();
IsUpdatingTranslations = false;
var index = line.IndexOf('=');
if (index == -1)
return line;
return line[..index];
}
}
private static ToolStripMenuItem GetTranslationUpdater()
private static string GetFileLocationInText(string fileType, string dir, string lang)
{
var fn = $"{fileType}_{lang}.txt";
return Path.Combine(dir, fn);
}
private static string GetResourcePath(params string[] subdir)
{
// Starting from the executable path, crawl upwards until we get to the repository/sln root
const string repo = "PKHeX";
var path = Application.StartupPath;
while (true)
{
var ti = new ToolStripMenuItem
{
ShortcutKeys = Keys.Control | Keys.Alt | Keys.D,
Visible = false,
};
ti.Click += (_, _) => UpdateAll();
return ti;
}
private static void UpdateTranslations()
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var types = assembly.GetTypes();
// Trigger a translation then dump all.
foreach (var lang in Languages) // get all languages ready to go
_ = WinFormsTranslator.GetDictionary(lang);
WinFormsTranslator.SetUpdateMode();
WinFormsTranslator.LoadSettings<PKHeXSettings>(DefaultLanguage);
WinFormsTranslator.LoadEnums(EnumTypesToTranslate, DefaultLanguage);
WinFormsTranslator.LoadAllForms(types, LoadBanlist); // populate with every possible control
WinFormsTranslator.TranslateControls(GetExtraControls(), DefaultLanguage);
var dir = GetResourcePath("PKHeX.WinForms", "Resources", "text");
WinFormsTranslator.DumpAll(DefaultLanguage, Banlist, dir); // dump current to file
WinFormsTranslator.SetUpdateMode(false);
// Move translated files from the debug exe loc to their project location
var files = Directory.GetFiles(Application.StartupPath);
foreach (var f in files)
{
var fn = Path.GetFileName(f);
if (!fn.EndsWith(".txt"))
continue;
if (!fn.StartsWith("lang_"))
continue;
var loc = Path.Combine(dir, fn);
if (File.Exists(loc))
File.Delete(loc);
File.Move(f, loc, true);
}
Application.Exit();
}
private static readonly Type[] EnumTypesToTranslate =
[
typeof(StatusCondition),
typeof(PokeSize),
typeof(PokeSizeDetailed),
typeof(PassPower5),
typeof(Funfest5Mission),
typeof(OPower6Index),
typeof(OPower6FieldType),
typeof(OPower6BattleType),
typeof(PlayerBattleStyle7),
typeof(PlayerSkinColor7),
typeof(Stamp7),
typeof(FestivalPlazaFacilityColor),
];
private static IEnumerable<Control> GetExtraControls()
{
foreach (var name in SlotList.GetEnumNames().Distinct())
yield return new Label { Name = $"{nameof(Main)}.L_{name}", Text = name };
}
private static readonly string[] LoadBanlist =
[
nameof(SplashScreen),
nameof(PokePreview),
];
private static readonly string[] Banlist =
[
"Gender=", // editor gender labels
"BTN_Shinytize", // ☆
"Hidden_", // Hidden controls
"CAL_", // calendar controls now expose Text, don't care.
".Count", // enum count
$"{nameof(Main)}.L_SizeH", // height rating
$"{nameof(Main)}.L_SizeW", // weight rating
$"{nameof(Main)}.L_SizeS", // scale rating
$"{nameof(Main)}.B_Box", // << and >> arrows
$"{nameof(Main)}.L_Characteristic=", // Characterstic (dynamic)
$"{nameof(Main)}.L_Potential", // ★☆☆☆ IV judge evaluation
$"{nameof(SAV_HoneyTree)}.L_Tree0", // dynamic, don't bother
$"{nameof(SAV_Misc3)}.BTN_Symbol", // symbols should stay as their current character
$"{nameof(SAV_GameSelect)}.L_Prompt", // prompt text (dynamic)
$"{nameof(SAV_BlockDump8)}.L_BlockName", // Block name (dynamic)
$"{nameof(SAV_PokedexResearchEditorLA)}.L_", // Dynamic label
$"{nameof(SAV_OPower)}.L_", // Dynamic label
];
private static void DumpStringsMessage() => DumpStrings(typeof(MessageStrings), false, "PKHeX.Core", "Resources", "text", "program");
private static void DumpStringsLegality() => DumpStrings(typeof(LegalityCheckStrings), true, "PKHeX.Core", "Resources", "legality", "checks");
private static void DumpStrings(Type t, bool sorted, params string[] rel)
{
var dir = GetResourcePath(rel);
DumpStrings(t, sorted, DefaultLanguage, dir);
foreach (var lang in Languages)
DumpStrings(t, sorted, lang, dir);
}
private static void DumpStrings(Type t, bool sorted, string lang, string dir)
{
LocalizationUtil.SetLocalization(t, lang);
var entries = LocalizationUtil.GetLocalization(t);
IEnumerable<string> export = entries.OrderBy(GetName); // sorted lines
if (!sorted)
export = entries;
var location = GetFileLocationInText(t.Name, dir, lang);
File.WriteAllLines(location, export);
LocalizationUtil.SetLocalization(t, DefaultLanguage);
static string GetName(string line)
{
var index = line.IndexOf('=');
if (index == -1)
return line;
return line[..index];
}
}
private static string GetFileLocationInText(string fileType, string dir, string lang)
{
var fn = $"{fileType}_{lang}.txt";
return Path.Combine(dir, fn);
}
private static string GetResourcePath(params string[] subdir)
{
// Starting from the executable path, crawl upwards until we get to the repository/sln root
const string repo = "PKHeX";
var path = Application.StartupPath;
while (true)
{
var parent = Directory.GetParent(path) ?? throw new DirectoryNotFoundException(path);
path = parent.FullName;
if (path.EndsWith(repo))
return Path.Combine(path, Path.Combine(subdir));
}
var parent = Directory.GetParent(path) ?? throw new DirectoryNotFoundException(path);
path = parent.FullName;
if (path.EndsWith(repo))
return Path.Combine(path, Path.Combine(subdir));
}
}
}

View File

@ -262,7 +262,7 @@ public static bool OpenSAVPKMDialog(IEnumerable<string> extensions, out string?
{
var sb = new StringBuilder(128);
foreach (var type in extensions)
sb.Append("*.").Append(type).Append(';');
sb.Append($"*.{type};");
sb.Append("*.pk");
string supported = sb.ToString();

View File

@ -1,4 +1,3 @@
using System;
using FluentAssertions;
using Xunit;

View File

@ -128,7 +128,7 @@ yield return
[0xF2AC8419, 0xADA208E3, 0xDB3A0BA6, 0x5EEF1076],
[0x9D28899D, 0xA3ECC9F0, 0x606EC6F0, 0x451FAE3C],
},
Delcatty
Delcatty,
];
yield return
[
@ -145,7 +145,7 @@ yield return
[0xC7315E32, 0x76566AA1, 0xC0CE436E, 0x98C45DA8, 0x9D1BDC4A],
[0xB687F0AF, 0xC01DB6C6, 0xAD6DEC75, 0xDB041314, 0x0D949325],
},
Butterfree
Butterfree,
];
}

View File

@ -54,9 +54,9 @@ private static void CheckStringGetSet(string check, string instr, string outstr,
private static string Hex(ReadOnlySpan<byte> outdata)
{
var sb = new System.Text.StringBuilder(outdata.Length);
var sb = new System.Text.StringBuilder(outdata.Length*3);
foreach (var b in outdata)
sb.Append(b.ToString("X2")).Append(' ');
sb.Append($"{b:X2} ");
return sb.ToString();
}