2020namespace Celeste . Mod . CollabUtils2 {
2121 public static class LobbyHelper {
2222
23+ internal static bool pauseTimerUntilAction = false ;
2324 private static bool unpauseTimerOnNextAction = false ;
2425
2526 private static ILHook hookOnOuiFileSelectRenderDisplayName ;
@@ -196,6 +197,9 @@ internal static void Load() {
196197 On . Celeste . OuiFileSelectSlot . Show += onOuiFileSelectSlotShow ;
197198 On . Celeste . OuiChapterPanel . UpdateStats += onChapterPanelUpdateStats ;
198199
200+ On . Monocle . Entity . Removed += onEntityRemoved ;
201+ On . Celeste . Overworld . End += onOverworldEnd ;
202+
199203 hookOnOuiFileSelectRenderDisplayName = new ILHook ( typeof ( OuiFileSelectSlot ) . GetMethod ( "orig_Render" ) , modSelectSlotLevelSetDisplayName ) ;
200204 hookOnOuiFileSelectRenderStrawberryStamp = new ILHook ( typeof ( OuiFileSelectSlot ) . GetMethod ( "orig_Render" ) , modSelectSlotCollectedStrawberries ) ;
201205 hookOnOuiJournalPoemLines = new ILHook ( typeof ( OuiJournalPoem ) . GetNestedType ( "PoemLine" , BindingFlags . NonPublic ) . GetMethod ( "Render" ) , modJournalPoemHeartColors ) ;
@@ -235,6 +239,9 @@ internal static void Unload() {
235239 On . Celeste . OuiFileSelectSlot . Show -= onOuiFileSelectSlotShow ;
236240 On . Celeste . OuiChapterPanel . UpdateStats -= onChapterPanelUpdateStats ;
237241
242+ On . Monocle . Entity . Removed -= onEntityRemoved ;
243+ On . Celeste . Overworld . End -= onOverworldEnd ;
244+
238245 hookOnOuiFileSelectRenderDisplayName ? . Dispose ( ) ;
239246 hookOnOuiFileSelectRenderStrawberryStamp ? . Dispose ( ) ;
240247 hookOnOuiJournalPoemLines ? . Dispose ( ) ;
@@ -317,9 +324,8 @@ public static void OnSessionCreated() {
317324 private static void onLoadLevel ( On . Celeste . Level . orig_LoadLevel orig , Level self , Player . IntroTypes playerIntro , bool isFromLoader ) {
318325 orig ( self , playerIntro , isFromLoader ) ;
319326
320- DynData < Session > sessionData = new DynData < Session > ( self . Session ) ;
321- if ( sessionData . Data . ContainsKey ( "pauseTimerUntilAction" ) && sessionData . Get < bool > ( "pauseTimerUntilAction" ) ) {
322- sessionData [ "pauseTimerUntilAction" ] = false ;
327+ if ( pauseTimerUntilAction ) {
328+ pauseTimerUntilAction = false ;
323329 self . TimerStopped = true ;
324330 unpauseTimerOnNextAction = true ;
325331 }
@@ -550,7 +556,7 @@ private static IEnumerator onAssistUnlockRoutine(On.Celeste.OuiChapterSelectIcon
550556 // we just assist unlocked the lobbies!
551557 LevelSetStats stats = SaveData . Instance . GetLevelSetStatsFor ( $ "{ collab } /0-Lobbies") ;
552558 stats . UnlockedAreas = stats . Areas . Count - 1 ;
553- List < OuiChapterSelectIcon > icons = new DynData < OuiChapterSelect > ( ( self . Scene as Overworld ) . GetUI < OuiChapterSelect > ( ) ) . Get < List < OuiChapterSelectIcon > > ( " icons" ) ;
559+ List < OuiChapterSelectIcon > icons = ( self . Scene as Overworld ) . GetUI < OuiChapterSelect > ( ) . icons ;
554560 icons [ self . Area + 1 ] . AssistModeUnlockable = false ;
555561 for ( int i = self . Area + 2 ; i <= SaveData . Instance . MaxArea ; i ++ ) {
556562 icons [ i ] . Show ( ) ;
@@ -573,6 +579,21 @@ private static void onJournalEnter(OuiJournal journal, Oui from) {
573579 }
574580 }
575581
582+ // those are Everest fields, so they aren't publicized :despair:
583+ private static readonly FieldInfo f_totalGoldenStrawberries = typeof ( OuiFileSelectSlot ) . GetField ( "totalGoldenStrawberries" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
584+ private static readonly FieldInfo f_totalHeartGems = typeof ( OuiFileSelectSlot ) . GetField ( "totalHeartGems" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
585+ private static readonly FieldInfo f_totalCassettes = typeof ( OuiFileSelectSlot ) . GetField ( "totalCassettes" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
586+ private static readonly FieldInfo f_maxStrawberryCount = typeof ( OuiFileSelectSlot ) . GetField ( "maxStrawberryCount" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
587+ private static readonly FieldInfo f_maxGoldenStrawberryCount = typeof ( OuiFileSelectSlot ) . GetField ( "maxGoldenStrawberryCount" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
588+ private static readonly FieldInfo f_maxStrawberryCountIncludingUntracked = typeof ( OuiFileSelectSlot ) . GetField ( "maxStrawberryCountIncludingUntracked" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
589+ private static readonly FieldInfo f_maxCassettes = typeof ( OuiFileSelectSlot ) . GetField ( "maxCassettes" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
590+ private static readonly FieldInfo f_maxCrystalHearts = typeof ( OuiFileSelectSlot ) . GetField ( "maxCrystalHearts" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
591+ private static readonly FieldInfo f_maxCrystalHeartsExcludingCSides = typeof ( OuiFileSelectSlot ) . GetField ( "maxCrystalHeartsExcludingCSides" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
592+ private static readonly FieldInfo f_summitStamp = typeof ( OuiFileSelectSlot ) . GetField ( "false" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
593+ private static readonly FieldInfo f_farewellStamp = typeof ( OuiFileSelectSlot ) . GetField ( "false" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
594+
595+ private static readonly Dictionary < OuiFileSelectSlot , List < string > > customHeartsPerSaveFileSlot = new Dictionary < OuiFileSelectSlot , List < string > > ( ) ;
596+
576597 private static void onOuiFileSelectSlotShow ( On . Celeste . OuiFileSelectSlot . orig_Show orig , OuiFileSelectSlot self ) {
577598 // If we are currently in a collab map, display the lobby level set stats instead.
578599 AreaKey ? savedLastArea = null ;
@@ -618,24 +639,23 @@ private static void onOuiFileSelectSlotShow(On.Celeste.OuiFileSelectSlot.orig_Sh
618639 }
619640 }
620641
621- DynData < OuiFileSelectSlot > slotData = new DynData < OuiFileSelectSlot > ( self ) ;
622- slotData [ "totalGoldenStrawberries" ] = totalGoldenStrawberries ;
623- slotData [ "totalHeartGems" ] = totalHeartGems ;
624- slotData [ "totalCassettes" ] = totalCassettes ;
625- slotData [ "maxStrawberryCount" ] = maxStrawberryCount ;
626- slotData [ "maxGoldenStrawberryCount" ] = maxGoldenStrawberryCount ;
627- slotData [ "maxStrawberryCountIncludingUntracked" ] = maxStrawberryCountIncludingUntracked ;
628- slotData [ "maxCassettes" ] = maxCassettes ;
629- slotData [ "maxCrystalHearts" ] = maxCrystalHearts ;
630- slotData [ "maxCrystalHeartsExcludingCSides" ] = maxCrystalHeartsExcludingCSides ;
631- slotData [ "summitStamp" ] = false ;
632- slotData [ "farewellStamp" ] = false ;
642+ f_totalGoldenStrawberries . SetValue ( self , totalGoldenStrawberries ) ;
643+ f_totalHeartGems . SetValue ( self , totalHeartGems ) ;
644+ f_totalCassettes . SetValue ( self , totalCassettes ) ;
645+ f_maxStrawberryCount . SetValue ( self , maxStrawberryCount ) ;
646+ f_maxGoldenStrawberryCount . SetValue ( self , maxGoldenStrawberryCount ) ;
647+ f_maxStrawberryCountIncludingUntracked . SetValue ( self , maxStrawberryCountIncludingUntracked ) ;
648+ f_maxCassettes . SetValue ( self , maxCassettes ) ;
649+ f_maxCrystalHearts . SetValue ( self , maxCrystalHearts ) ;
650+ f_maxCrystalHeartsExcludingCSides . SetValue ( self , maxCrystalHeartsExcludingCSides ) ;
651+ f_summitStamp . SetValue ( self , false ) ;
652+ f_farewellStamp . SetValue ( self , false ) ;
633653
634654 self . Strawberries . Amount = totalStrawberries ;
635655 self . Strawberries . OutOf = maxStrawberryCount ;
636656 }
637657
638- // figure out if some hearts are customized, and store it in DynData so that a IL hook can access it later.
658+ // figure out if some hearts are customized, and store it in a static variable so that an IL hook can access it later.
639659 SaveData oldInstance = SaveData . Instance ;
640660 SaveData . Instance = self . SaveData ;
641661 List < string > customJournalHearts = new List < string > ( ) ;
@@ -654,7 +674,7 @@ private static void onOuiFileSelectSlotShow(On.Celeste.OuiFileSelectSlot.orig_Sh
654674 }
655675 }
656676 }
657- new DynData < OuiFileSelectSlot > ( self ) [ "collabutils2_customhearts" ] = customJournalHearts ;
677+ customHeartsPerSaveFileSlot [ self ] = customJournalHearts ;
658678 SaveData . Instance = oldInstance ;
659679
660680 // Restore the last area if it was replaced at the beginning of this method.
@@ -668,7 +688,7 @@ private static void onChapterPanelUpdateStats(On.Celeste.OuiChapterPanel.orig_Up
668688
669689 if ( IsCollabLobby ( self . Area . SID ) ) {
670690 // hide the deaths counter for collab lobbies.
671- new DynData < OuiChapterPanel > ( self ) . Get < DeathsCounter > ( " deaths" ) . Visible = false ;
691+ self . deaths . Visible = false ;
672692 }
673693 }
674694
@@ -763,13 +783,23 @@ private static void modOuiFileSelectSlotRender(ILContext il) {
763783 }
764784
765785 private static MTexture reskinJournalHearts ( MTexture orig , OuiFileSelectSlot self , int index ) {
766- List < string > customJournalHearts = new DynData < OuiFileSelectSlot > ( self ) . Get < List < string > > ( "collabutils2_customhearts" ) ;
786+ List < string > customJournalHearts = customHeartsPerSaveFileSlot . GetValueOrDefault ( self ) ;
767787 if ( customJournalHearts != null && customJournalHearts [ index ] != null ) {
768788 return MTN . Journal [ customJournalHearts [ index ] ] ; // "Journal" and not "FileSelect" because it re-uses the setup people made for their custom journals.
769789 }
770790 return orig ;
771791 }
772792
793+ private static void onEntityRemoved ( On . Monocle . Entity . orig_Removed orig , Monocle . Entity self , Scene scene ) {
794+ if ( self is OuiFileSelectSlot slot ) customHeartsPerSaveFileSlot . Remove ( slot ) ;
795+ orig ( self , scene ) ;
796+ }
797+
798+ private static void onOverworldEnd ( On . Celeste . Overworld . orig_End orig , Overworld self ) {
799+ customHeartsPerSaveFileSlot . Clear ( ) ;
800+ orig ( self ) ;
801+ }
802+
773803 private static void modJournalPoemHeartColors ( ILContext il ) {
774804 ILCursor cursor = new ILCursor ( il ) ;
775805
0 commit comments