PKHeX/PKHeX.Core/Editing/Saves/Slots/SlotChangelog.cs
Kurt 02420d3e93
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases

Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization

* Handle bits more obviously without null

* Make SaveFile.BAK explicitly readonly again

* merge constructor methods to have readonly fields

* Inline some properties

* More nullable handling

* Rearrange box actions

define straightforward classes to not have any null properties

* Make extrabyte reference array immutable

* Move tooltip creation to designer

* Rearrange some logic to reduce nesting

* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum

* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case

* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable

* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator

* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever

* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)

* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-16 18:47:31 -07:00

87 lines
No EOL
2.6 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 sealed 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()
{
var change = UndoStack.Pop();
var revert = GetReversion(change.Info, SAV);
AddRedo(revert);
change.Revert(SAV);
return change.Info;
}
public ISlotInfo Redo()
{
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)
{
return info switch
{
SlotInfoParty p => (SlotReversion) new PartyReversion(p, sav),
_ => 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);
}
}
}