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 class QRMessageUtil
/// <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 @@ public readonly record struct MoveLearnInfo(LearnMethod Method, LearnEnvironment
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 readonly record struct NPCLock
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 class GenerateMethodK
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 @@ public sealed class WB8(byte[] Data) : DataMysteryGift(Data),
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 @@ public sealed class WB8(byte[] Data) : DataMysteryGift(Data),
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 class TrainerInfoExtensions
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 class TrainerInfoExtensions
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 class SCBlockUtil
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 @@ public abstract class SAV4 : SaveFile, IEventFlag37, IDaycareStorage, IDaycareRa
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 @@ public sealed class SecretBase3PKM : ISpeciesForm
{
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 sealed class Record4(SAV4 SAV, Memory<byte> raw) : SaveBlock<SAV4>(SAV, r
/// </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 @@ public sealed class Record4(SAV4 SAV, Memory<byte> raw) : SaveBlock<SAV4>(SAV, r
{
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 @@ public sealed class Record4(SAV4 SAV, Memory<byte> raw) : SaveBlock<SAV4>(SAV, r
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 class DateUtil
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 class FileUtil
/// <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 @@ public partial class SAV_Misc3 : Form
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 @@ public partial class SAV_Misc4 : Form
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 @@ public partial class SAV_Misc4 : Form
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 partial class SAV_Raid8 : Form
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 @@ public partial class SAV_PokedexSVKitakami : Form
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 partial class SAV_Raid9 : Form
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 System.Windows.Forms;
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 class WinFormsUtil
{
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 @@ public static class PIDTests
[0xF2AC8419, 0xADA208E3, 0xDB3A0BA6, 0x5EEF1076],
[0x9D28899D, 0xA3ECC9F0, 0x606EC6F0, 0x451FAE3C],
},
Delcatty
Delcatty,
];
yield return
[
@ -145,7 +145,7 @@ public static class PIDTests
[0xC7315E32, 0x76566AA1, 0xC0CE436E, 0x98C45DA8, 0x9D1BDC4A],
[0xB687F0AF, 0xC01DB6C6, 0xAD6DEC75, 0xDB041314, 0x0D949325],
},
Butterfree
Butterfree,
];
}

View file

@ -54,9 +54,9 @@ public class StringTests
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();
}