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)
This commit is contained in:
montanon 2026-03-16 19:47:02 -03:00
parent 159f7d573d
commit 137c72e55e

View File

@ -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)
{