1+ using System . Reflection ;
12using System . Runtime . CompilerServices ;
23using System . Text . Json ;
34using MegaCrit . Sts2 . Core . Achievements ;
45using MegaCrit . Sts2 . Core . Models ;
56using MegaCrit . Sts2 . Core . Saves ;
7+ using MegaCrit . Sts2 . Core . Saves . Validation ;
68using MegaCrit . Sts2 . Core . Timeline ;
79
810namespace STS2RitsuLib . Saves
@@ -15,6 +17,10 @@ public sealed class PreservedProgressRecords
1517 {
1618 private static readonly ConditionalWeakTable < ProgressState , PreservedProgressRecords > RecordsByProgress = new ( ) ;
1719 private static readonly HashSet < string > KnownAchievementNames = BuildKnownAchievementNames ( ) ;
20+
21+ private static readonly FieldInfo ? ValidationErrorsField =
22+ typeof ( DeserializationContext ) . GetField ( "_errors" , BindingFlags . Instance | BindingFlags . NonPublic ) ;
23+
1824 private readonly List < AncientStats > _ancientStats = [ ] ;
1925 private readonly List < CardStats > _cardStats = [ ] ;
2026
@@ -80,6 +86,19 @@ internal static void Attach(ProgressState? progress, PreservedProgressRecords? r
8086 RitsuLibFramework . Logger . Info ( $ "[Saves] Preserving unavailable progress records: { records . FormatCounts ( ) } ") ;
8187 }
8288
89+ internal int SuppressExpectedWarnings ( DeserializationContext ctx )
90+ {
91+ if ( ValidationErrorsField ? . GetValue ( ctx ) is not List < ValidationError > errors )
92+ return 0 ;
93+
94+ var removed = errors . RemoveAll ( IsExpectedPreservedWarning ) ;
95+ if ( removed > 0 )
96+ RitsuLibFramework . Logger . Info (
97+ $ "[Saves] Suppressed { removed } expected progress validation warning(s) for unavailable preserved records") ;
98+
99+ return removed ;
100+ }
101+
83102 internal static void MergeInto ( ProgressState ? progress , SerializableProgress ? save )
84103 {
85104 if ( progress == null || save == null )
@@ -306,6 +325,61 @@ private static string FormatCount(string label, int count)
306325 return count > 0 ? $ "{ label } ={ count } " : "" ;
307326 }
308327
328+ private bool IsExpectedPreservedWarning ( ValidationError error )
329+ {
330+ if ( error . IsFatal || ! error . Message . StartsWith ( "Unknown " , StringComparison . Ordinal ) )
331+ return false ;
332+
333+ var modelIds = GetPreservedModelIdStrings ( ) ;
334+ foreach ( var id in modelIds )
335+ if ( error . Message . Contains ( id , StringComparison . Ordinal ) )
336+ return true ;
337+
338+ foreach ( var epochId in _epochs . Select ( static epoch => epoch . Id ) )
339+ if ( error . Message . Contains ( epochId , StringComparison . Ordinal ) )
340+ return true ;
341+
342+ foreach ( var achievement in _unlockedAchievements . Select ( static item => item . Achievement ) )
343+ if ( error . Message . Contains ( '"' + achievement + '"' , StringComparison . Ordinal ) )
344+ return true ;
345+
346+ return false ;
347+ }
348+
349+ private HashSet < string > GetPreservedModelIdStrings ( )
350+ {
351+ var ids = new HashSet < string > ( StringComparer . Ordinal ) ;
352+ AddIds ( ids , _characterStats . Select ( static stats => stats . Id ) ) ;
353+ AddIds ( ids , _cardStats . Select ( static stats => stats . Id ) ) ;
354+ AddIds ( ids , _encounterStats . Select ( static stats => stats . Id ) ) ;
355+ AddIds ( ids , _enemyStats . Select ( static stats => stats . Id ) ) ;
356+ AddIds ( ids , _ancientStats . Select ( static stats => stats . Id ) ) ;
357+ AddIds ( ids , _encounterStats . SelectMany ( static stats =>
358+ stats . FightStats . Select ( static fight => fight . Character ) ) ) ;
359+ AddIds ( ids ,
360+ _enemyStats . SelectMany ( static stats => stats . FightStats . Select ( static fight => fight . Character ) ) ) ;
361+ AddIds ( ids , _ancientStats . SelectMany ( static stats =>
362+ stats . CharStats . Select ( static charStats => charStats . Character ) ) ) ;
363+ AddIds ( ids , _discoveredCards ) ;
364+ AddIds ( ids , _discoveredRelics ) ;
365+ AddIds ( ids , _discoveredPotions ) ;
366+ AddIds ( ids , _discoveredEvents ) ;
367+ AddIds ( ids , _discoveredActs ) ;
368+
369+ if ( _pendingCharacterUnlock is { } pendingCharacterUnlock &&
370+ pendingCharacterUnlock != ModelId . none )
371+ ids . Add ( pendingCharacterUnlock . ToString ( ) ) ;
372+
373+ return ids ;
374+ }
375+
376+ private static void AddIds ( HashSet < string > target , IEnumerable < ModelId ? > source )
377+ {
378+ foreach ( var id in source )
379+ if ( id is { } modelId && modelId != ModelId . none )
380+ target . Add ( modelId . ToString ( ) ) ;
381+ }
382+
309383 private static bool IsUnknownModel < TModel > ( ModelId ? id )
310384 where TModel : AbstractModel
311385 {
0 commit comments