From 137c72e55ec0f66263cc7690b24e8505f24ba2df Mon Sep 17 00:00:00 2001 From: montanon Date: Mon, 16 Mar 2026 19:47:02 -0300 Subject: [PATCH] Fix saboteur-found bugs: egg dates, unclamped casts, version guard Egg un-toggle date sync (matching WinForms): - Met date synced from egg date when un-egging with egg location - Met date set to today when un-egging without egg location - Egg dates always reset to 0/1/1 on un-egg Unclamped cast fixes (prevent data corruption): - ShadowID: clamp 0-65535 before ushort cast - ExtraByteValue: clamp 0-255 before byte cast - MetTimeOfDay: clamp 0-3 - AlphaMove: clamp 0-65535 before ushort cast Reentrancy fix: - OnSelectedVersionChanged: guard RefreshLocationLists with _isPopulating check to prevent cascading during PopulateFields Confirmed NOT a bug: - Slot click without save: WinForms also doesn't auto-save (edits live in editor until explicit Set via Shift+click) --- .../ViewModels/PKMEditorViewModel.cs | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs b/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs index 3b9c78037..11208a048 100644 --- a/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs +++ b/PKHeX.Avalonia/ViewModels/PKMEditorViewModel.cs @@ -549,7 +549,7 @@ private void RerollPid() { if (_isPopulating || SelectedExtraByteOffset is null || Entity is null) return; if (ushort.TryParse(SelectedExtraByteOffset.Replace("0x", ""), System.Globalization.NumberStyles.HexNumber, null, out var offset) && offset < Entity.Data.Length) - Entity.Data[offset] = (byte)value; + Entity.Data[offset] = (byte)Math.Clamp(value, 0, 255); } // Met — Fateful Encounter @@ -926,9 +926,12 @@ private void UpdateBallSprite() partial void OnSelectedVersionChanged(ComboItem? value) { if (value is not null) - { Version = value.Value; + if (!_isPopulating && Entity is not null) + { + Entity.Version = (GameVersion)Version; RefreshLocationLists(); + UpdateLegality(); } } @@ -1969,7 +1972,7 @@ public void PopulateFields(PKM pk) // Gen-specific: Shadow Pokemon (XD/Colosseum) if (Entity is IShadowCapture scSave) { - scSave.ShadowID = (ushort)ShadowId; + scSave.ShadowID = (ushort)Math.Clamp(ShadowId, 0, 65535); scSave.Purification = Purification; // IsShadow is derived from ShadowID/Purification, no separate write needed } @@ -1991,7 +1994,7 @@ public void PopulateFields(PKM pk) // Met — Time of Day (Gen 2) if (Entity is ICaughtData2 cd2Save) - cd2Save.MetTimeOfDay = MetTimeOfDay; + cd2Save.MetTimeOfDay = Math.Clamp(MetTimeOfDay, 0, 3); // Met — As Egg: if unchecked, clear egg location if (!MetAsEgg) @@ -2035,7 +2038,7 @@ public void PopulateFields(PKM pk) // Alpha Mastered Move (Legends Arceus) if (Entity is PA8 pa8Save && SelectedAlphaMove is not null) - pa8Save.AlphaMove = (ushort)SelectedAlphaMove.Value; + pa8Save.AlphaMove = (ushort)Math.Clamp(SelectedAlphaMove.Value, 0, 65535); // Post-save cleanup (matching WinForms SaveFields) Entity.FixMoves(); @@ -2360,6 +2363,40 @@ private async Task ShowFullLegalityReport() Friendship = Math.Clamp((int)Entity.PersonalInfo.BaseFriendship, 0, 255); Entity.CurrentFriendship = (byte)Friendship; + // Sync met date from egg date, or set to today + if (Entity.EggLocation != 0) + { + _isPopulating = true; + try + { + MetYear = EggYear; MetMonth = EggMonth; MetDay = EggDay; + Entity.MetYear = (byte)Math.Clamp(EggYear, 0, 255); + Entity.MetMonth = (byte)Math.Clamp(EggMonth, 1, 12); + Entity.MetDay = (byte)Math.Clamp(EggDay, 1, 31); + } + finally { _isPopulating = false; } + } + else + { + // No egg location: set met date to today + var now = DateTime.Now; + _isPopulating = true; + try + { + MetYear = now.Year - 2000; MetMonth = now.Month; MetDay = now.Day; + } + finally { _isPopulating = false; } + } + + // Reset egg dates + _isPopulating = true; + try + { + EggYear = 0; EggMonth = 1; EggDay = 1; + Entity.EggYear = 0; Entity.EggMonth = 1; Entity.EggDay = 1; + } + finally { _isPopulating = false; } + // If no egg location, set reasonable defaults for no-longer-egg if (EggLocation == 0) {