82 lines
3.4 KiB
C#
82 lines
3.4 KiB
C#
#nullable enable
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace ReplacedPerson.Core
|
|
{
|
|
[Serializable]
|
|
public sealed class ReplacedPersonSaveData
|
|
{
|
|
public const int CurrentVersion = 3;
|
|
public int Version { get; set; } = CurrentVersion;
|
|
public int ChapterProgress { get; set; }
|
|
public List<string> CollectedCards { get; set; } = new();
|
|
public List<string> Ornaments { get; set; } = new();
|
|
public List<string> EquippedOrnaments { get; set; } = new();
|
|
public ReplacedDeck ActiveDeck { get; set; } = ReplacedBuiltInContent.CreateStarterDeck();
|
|
public List<ReplacedMatchCommand> RecentReplay { get; set; } = new();
|
|
}
|
|
|
|
public static class ReplacedPersonSaveMigration
|
|
{
|
|
public static ReplacedPersonSaveData Migrate(ReplacedPersonSaveData source)
|
|
{
|
|
if (source == null) throw new ArgumentNullException(nameof(source));
|
|
if (source.Version > ReplacedPersonSaveData.CurrentVersion)
|
|
throw new InvalidOperationException("Save data comes from a newer version.");
|
|
source.CollectedCards ??= new List<string>();
|
|
source.Ornaments ??= new List<string>();
|
|
source.EquippedOrnaments ??= new List<string>();
|
|
source.ActiveDeck ??= ReplacedBuiltInContent.CreateStarterDeck();
|
|
source.RecentReplay ??= new List<ReplacedMatchCommand>();
|
|
if (source.Version < 2)
|
|
{
|
|
if (source.ChapterProgress > 0 && !source.Ornaments.Contains("ornament.gold-eye"))
|
|
source.Ornaments.Add("ornament.gold-eye");
|
|
source.Version = 2;
|
|
}
|
|
if (source.Version < 3)
|
|
{
|
|
var starter = ReplacedBuiltInContent.CreateStarterDeck();
|
|
if (IsLegacyStarter(source.ActiveDeck)) source.ActiveDeck = starter;
|
|
EnsureOwnedCopies(source.CollectedCards, starter.NormalCards);
|
|
source.Version = 3;
|
|
}
|
|
return source;
|
|
}
|
|
|
|
public static ReplacedPersonSaveData CreateNew()
|
|
{
|
|
var deck = ReplacedBuiltInContent.CreateStarterDeck();
|
|
return new ReplacedPersonSaveData
|
|
{
|
|
ActiveDeck = deck,
|
|
CollectedCards = new List<string>(deck.NormalCards)
|
|
};
|
|
}
|
|
|
|
private static bool IsLegacyStarter(ReplacedDeck deck)
|
|
{
|
|
var legacy = new[]
|
|
{
|
|
"attack.kill", "attack.kill", "attack.elbow", "attack.elbow", "attack.break", "attack.break",
|
|
"dodge.flash", "dodge.flash", "dodge.phase", "dodge.phase", "counter.blood", "counter.blood"
|
|
};
|
|
return deck.NormalCards.OrderBy(value => value, StringComparer.Ordinal)
|
|
.SequenceEqual(legacy.OrderBy(value => value, StringComparer.Ordinal)) &&
|
|
deck.EndCards.SequenceEqual(new[] { "end.inherit", "end.ledger", "end.severance", "end.black" });
|
|
}
|
|
|
|
private static void EnsureOwnedCopies(List<string> collection, IEnumerable<string> starterCards)
|
|
{
|
|
foreach (var group in starterCards.GroupBy(value => value, StringComparer.Ordinal))
|
|
{
|
|
var missing = group.Count() - collection.Count(value => value == group.Key);
|
|
for (var i = 0; i < missing; i++) collection.Add(group.Key);
|
|
}
|
|
}
|
|
}
|
|
}
|