PKHeX/PKHeX.Core/Editing/Saves/Slots/SlotChangelog.cs
Kurt b81a1e1e29 Refactoring
Increase abstraction for arbitrary slot get/set operations, and fracture
SAV4 behavior for each game type.

Adds: Undo/Redo of party slot changes
Fixes: Fixed Gen5 daycare slot 2 reading, and EXP reading
Fixes: Some slot color glitchiness
Fixed: Box layout editor now hides the flag label if no flags are
present
Fixed: Gen7 box flags are now shown (unknown purpose lol)
Changed: savefile objects are generally smaller (removed a few shared
offset fields)
2019-09-02 19:30:58 -07:00

95 lines
No EOL
2.7 KiB
C#

using System.Collections.Generic;
namespace PKHeX.Core
{
/// <summary>
/// Tracks <see cref="PKM"/> slot changes and provides the ability to revert a change.
/// </summary>
public class SlotChangelog
{
private readonly SaveFile SAV;
private readonly Stack<SlotReversion> UndoStack = new Stack<SlotReversion>();
private readonly Stack<SlotReversion> RedoStack = new Stack<SlotReversion>();
public SlotChangelog(SaveFile sav) => SAV = sav;
public bool CanUndo => UndoStack.Count != 0;
public bool CanRedo => RedoStack.Count != 0;
public void AddNewChange(ISlotInfo info)
{
var revert = GetReversion(info, SAV);
AddUndo(revert);
}
public ISlotInfo Undo()
{
if (!CanUndo)
return null;
var change = UndoStack.Pop();
var revert = GetReversion(change.Info, SAV);
AddRedo(revert);
change.Revert(SAV);
return change.Info;
}
public ISlotInfo Redo()
{
if (!CanRedo)
return null;
var change = RedoStack.Pop();
var revert = GetReversion(change.Info, SAV);
AddUndo(revert);
change.Revert(SAV);
return change.Info;
}
private void AddRedo(SlotReversion change)
{
RedoStack.Push(change);
}
private void AddUndo(SlotReversion change)
{
UndoStack.Push(change);
RedoStack.Clear();
}
private static SlotReversion GetReversion(ISlotInfo info, SaveFile sav)
{
switch (info)
{
case SlotInfoParty p:
return new PartyReversion(p, sav);
default:
return new SingleSlotReversion(info, sav);
}
}
private abstract class SlotReversion
{
internal readonly ISlotInfo Info;
protected SlotReversion(ISlotInfo info) => Info = info;
public abstract void Revert(SaveFile sav);
}
private class PartyReversion : SlotReversion
{
private readonly IList<PKM> Party;
public PartyReversion(ISlotInfo info, SaveFile s) : base(info) => Party = s.PartyData;
public override void Revert(SaveFile sav) => sav.PartyData = Party;
}
private class SingleSlotReversion : SlotReversion
{
private readonly PKM PKM;
public SingleSlotReversion(ISlotInfo info, SaveFile sav) : base(info) => PKM = info.Read(sav);
public override void Revert(SaveFile sav) => Info.WriteTo(sav, PKM, PKMImportSetting.Skip);
}
}
}