private static void Load()
 {
     On.Celeste.Strawberry.Added += StrawberryOnAdded;
     IL.Celeste.SpeedrunTimerDisplay.DrawTime += SetSaveStateColor;
     IL.Celeste.Level.Reload += LevelOnReload;
     SaveLoadAction.Add(new SaveLoadAction(ReColor, ReColor));
 }
        private void ClearState(bool clearEndPoint)
        {
            if (Engine.Scene is Level level && IsNotCollectingHeart(level) && !level.Completed)
            {
                level.Frozen    = false;
                level.PauseLock = false;
            }

            RoomTimerManager.Instance.ClearPbTimes(clearEndPoint);

            playingEventInstances.Clear();

            savedModSessions = null;
            savedLevel       = null;
            savedEntities?.Clear();
            savedEntities = null;
            savedOrderedTrackerEntities?.Clear();
            savedOrderedTrackerEntities = null;
            savedOrderedTrackerComponents?.Clear();
            savedOrderedTrackerComponents = null;

            preCloneTask = null;

            DeepClonerUtils.ClearSharedDeepCloneState();

            // Mod
            SaveLoadAction.OnClearState();

            SavedByTas = false;

            State = States.None;
        }
        // public for TAS Mod
        // ReSharper disable once MemberCanBePrivate.Global
        public bool LoadState()
        {
            if (!(Engine.Scene is Level level))
            {
                return(false);
            }
            if (level.Paused || state != States.None || !IsSaved)
            {
                return(false);
            }

            state = States.Loading;

            // External
            RoomTimerManager.Instance.ResetTime();
            DeathStatisticsManager.Instance.Died = false;

            // Mod
            SaveLoadAction.OnLoadState(level);

            level.SetFieldValue("transition", null); // 允许切换房间时读档
            level.Displacement.Clear();              // 避免冲刺后读档残留爆破效果
            TrailManager.Clear();                    // 清除冲刺的残影

            UnloadLevelEntities(level);
            RestoreLevelEntities(level);
            RestoreCassetteBlockManager(level);
            RestoreLevel(level);

            // restore all mod sessions
            foreach (EverestModule module in Everest.Modules)
            {
                if (savedModSessions.TryGetValue(module, out EverestModuleSession savedModSession))
                {
                    module._Session = savedModSession.DeepCloneYaml(module.SessionType);
                }
            }

            // 修复问题:未打开自动读档时,死掉按下确认键后读档完成会接着执行 Reload 复活方法
            if (level.RendererList.Renderers.FirstOrDefault(renderer => renderer is ScreenWipe) is ScreenWipe wipe)
            {
                wipe.Cancel();
            }

            level.Frozen       = true; // 加一个转场等待,避免太突兀
            level.TimerStopped = true; // 停止计时器

            level.DoScreenWipe(true, () => {
                RestoreLevel(level);
                RoomTimerManager.Instance.SavedEndPoint?.ReadyForTime();
                foreach (EventInstance instance in playingEventInstances)
                {
                    instance.start();
                }
                state = States.None;
            });

            return(true);
        }
 public void OnUnload()
 {
     DeepCloneUtils.Clear();
     SaveLoadAction.OnUnload();
     EventInstanceUtils.OnUnhook();
     On.Celeste.Level.Update       -= CheckButtonsOnLevelUpdate;
     On.Monocle.Scene.Begin        -= ClearStateWhenSwitchScene;
     On.Celeste.PlayerDeadBody.End -= AutoLoadStateWhenDeath;
 }
 public void OnLoad()
 {
     DeepClonerUtils.Config();
     SaveLoadAction.OnLoad();
     EventInstanceUtils.OnHook();
     StateMarkUtils.OnLoad();
     On.Celeste.Level.Update       += CheckButtonsAndUpdateBackdrop;
     On.Monocle.Scene.Begin        += ClearStateWhenSwitchScene;
     On.Celeste.PlayerDeadBody.End += AutoLoadStateWhenDeath;
 }
        // public for TAS Mod
        // ReSharper disable once MemberCanBePrivate.Global UnusedMethodReturnValue.Global
        public bool SaveState()
        {
            if (!(Engine.Scene is Level level))
            {
                return(false);
            }
            if (!IsAllowSave(level, level.GetPlayer()))
            {
                return(false);
            }

            ClearState(false);

            savedLevel         = level.ShallowClone();
            savedLevel.Session = level.Session.DeepClone();
            savedLevel.Camera  = level.Camera.DeepClone();

            savedEntities = DeepCloneEntities(GetEntitiesExcludingGlobal(level));

            savedCassetteBlockManager = level.Entities.FindFirst <CassetteBlockManager>()?.ShallowClone();

            // External
            savedFreezeTimer     = Engine.FreezeTimer;
            savedTimeRate        = Engine.TimeRate;
            savedGlitchValue     = Glitch.Value;
            savedDistortAnxiety  = Distort.Anxiety;
            savedDistortGameRate = Distort.GameRate;

            // Mod
            SaveLoadAction.OnSaveState(level);

            // save all mod sessions
            savedModSessions = new Dictionary <EverestModule, EverestModuleSession>();
            foreach (EverestModule module in Everest.Modules)
            {
                if (module._Session != null)
                {
                    savedModSessions[module] = module._Session.DeepCloneYaml(module.SessionType);
                }
            }

            return(LoadState());
        }
        private void ClearState(bool clearEndPoint = true)
        {
            if (Engine.Scene is Level level && IsNotCollectingHeart(level))
            {
                level.Frozen    = false;
                level.PauseLock = false;
            }
            try { RoomTimerManager.Instance.ClearPbTimes(clearEndPoint); }
            catch (NullReferenceException) { }

            savedModSessions          = null;
            savedLevel                = null;
            savedEntities             = null;
            savedCassetteBlockManager = null;

            // Mod
            SaveLoadAction.OnClearState();

            state = States.None;
        }
        private bool LoadState(bool tas)
        {
            if (!(Engine.Scene is Level level))
            {
                return(false);
            }
            if (level.PausedNew() || State != States.None || !IsSaved)
            {
                return(false);
            }
            if (tas && !SavedByTas)
            {
                return(false);
            }

            State = States.Loading;
            DeepClonerUtils.SetSharedDeepCloneState(preCloneTask?.Result);

            // 修复问题:死亡瞬间读档 PlayerDeadBody 没被清除,导致读档完毕后 madeline 自动 retry
            level.Entities.UpdateLists();

            // External
            RoomTimerManager.Instance.ResetTime();
            DeathStatisticsManager.Instance.Died = false;

            level.Displacement.Clear(); // 避免冲刺后读档残留爆破效果  // Remove dash displacement effect
            level.Particles.Clear();
            level.ParticlesBG.Clear();
            level.ParticlesFG.Clear();
            TrailManager.Clear(); // 清除冲刺的残影  // Remove dash trail

            UnloadLevelEntities(level);

            GC.Collect();
            GC.WaitForPendingFinalizers();

            RestoreLevelEntities(level);
            RestoreCassetteBlockManager1(level); // 停止播放主音乐,等待播放节奏音乐
            RestoreLevel(level);

            // Mod 和其他
            SaveLoadAction.OnLoadState(level);

            // restore all mod sessions
            foreach (EverestModule module in Everest.Modules)
            {
                if (savedModSessions.TryGetValue(module, out EverestModuleSession savedModSession))
                {
                    module._Session = savedModSession.DeepCloneShared();
                }
            }

            // 修复问题:未打开自动读档时,死掉按下确认键后读档完成会接着执行 Reload 复活方法
            // Fix: When AutoLoadStateAfterDeath is off, if manually LoadState() after death, level.Reload() will still be executed.
            ClearScreenWipe(level);

            if (tas)
            {
                LoadStateComplete(level);
                return(true);
            }

            level.Frozen       = true; // 加一个转场等待,避免太突兀   // Add a pause to avoid being too abrupt
            level.TimerStopped = true; // 停止计时器  // Stop timer

            level.DoScreenWipe(true, () => {
                // 修复问题:死亡后出现黑屏的一瞬间手动读档后游戏崩溃,因为 ScreenWipe 执行了 level.Reload() 方法
                // System.NullReferenceException: 未将对象引用设置到对象的实例。
                // 在 Celeste.CameraTargetTrigger.OnLeave(Player player)
                // 在 Celeste.Player.Removed(Scene scene)
                ClearScreenWipe(level);

                LoadStateEnd(level);
            });

            return(true);
        }
        private bool SaveState(bool tas)
        {
            if (!(Engine.Scene is Level level))
            {
                return(false);
            }
            if (!IsAllowSave(level, level.GetPlayer()))
            {
                return(false);
            }
            // 不允许玩家在黑屏时保存状态,因为如果在黑屏结束一瞬间之前保存,读档后没有黑屏等待时间感觉会很突兀
            if (!tas && level.Wipe != null)
            {
                return(false);
            }

            // 不允许在春游图打开章节面板时存档
            if (inGameOverworldHelperIsOpen.Value?.GetValue(null) as bool? == true)
            {
                return(false);
            }

            ClearState(false);

            SavedByTas = tas;

            savedLevel = level.ShallowClone();
            savedLevel.FormationBackdrop = level.FormationBackdrop.ShallowClone();
            savedLevel.Session           = level.Session.DeepCloneShared();
            savedLevel.Camera            = level.Camera.DeepCloneShared();

            // Renderer
            savedLevel.Bloom      = level.Bloom.DeepCloneShared();
            savedLevel.Background = level.Background.DeepCloneShared();
            savedLevel.Foreground = level.Foreground.DeepCloneShared();
            // savedLevel.HudRenderer = level.HudRenderer.DeepCloneShared();
            // savedLevel.SubHudRenderer = level.SubHudRenderer.DeepCloneShared();
            // savedLevel.Displacement = level.Displacement.DeepCloneShared();

            // 只需浅克隆
            savedLevel.Lighting = level.Lighting.ShallowClone();

            // 无需克隆,且里面有 camera
            // savedLevel.GameplayRenderer = level.GameplayRenderer.DeepCloneShared();

            // Renderer nullable
            // savedLevel.Wipe = level.Wipe.DeepCloneShared();

            savedLevel.SetFieldValue("transition", level.GetFieldValue("transition").DeepCloneShared());
            savedLevel.SetFieldValue("skipCoroutine", level.GetFieldValue("skipCoroutine").DeepCloneShared());
            savedLevel.SetFieldValue("onCutsceneSkip", level.GetFieldValue("onCutsceneSkip").DeepCloneShared());
            // savedLevel.SetPropertyValue<Scene>("RendererList", level.RendererList.DeepCloneShared());

            savedEntities = GetEntitiesNeedDeepClone(level).DeepCloneShared();

            savedOrderedTrackerEntities = new Dictionary <Type, Dictionary <Entity, int> >();
            foreach (Entity savedEntity in savedEntities)
            {
                Type type = savedEntity.GetType();
                if (savedOrderedTrackerEntities.ContainsKey(type))
                {
                    continue;
                }

                if (level.Tracker.Entities.ContainsKey(type) && level.Tracker.Entities[type].Count > 0)
                {
                    List <Entity>            clonedEntities = level.Tracker.Entities[type].DeepCloneShared();
                    Dictionary <Entity, int> dictionary     = new Dictionary <Entity, int>();
                    for (var i = 0; i < clonedEntities.Count; i++)
                    {
                        dictionary[clonedEntities[i]] = i;
                    }
                    savedOrderedTrackerEntities[type] = dictionary;
                }
            }

            savedOrderedTrackerComponents = new Dictionary <Type, Dictionary <Component, int> >();
            foreach (Component component in savedEntities.SelectMany(entity => entity.Components))
            {
                Type type = component.GetType();
                if (savedOrderedTrackerComponents.ContainsKey(type))
                {
                    continue;
                }

                if (level.Tracker.Components.ContainsKey(type) && level.Tracker.Components[type].Count > 0)
                {
                    List <Component>            clonedComponents = level.Tracker.Components[type].DeepCloneShared();
                    Dictionary <Component, int> dictionary       = new Dictionary <Component, int>();
                    for (var i = 0; i < clonedComponents.Count; i++)
                    {
                        dictionary[clonedComponents[i]] = i;
                    }
                    savedOrderedTrackerComponents[type] = dictionary;
                }
            }

            // External
            savedFreezeTimer     = Engine.FreezeTimer;
            savedTimeRate        = Engine.TimeRate;
            savedDeltaTime       = Engine.DeltaTime;
            savedRawDeltaTime    = Engine.RawDeltaTime;
            savedFrameCounter    = Engine.FrameCounter;
            savedGlitchValue     = Glitch.Value;
            savedDistortAnxiety  = Distort.Anxiety;
            savedDistortGameRate = Distort.GameRate;

            // Mod 和其他
            SaveLoadAction.OnSaveState(level);

            // save all mod sessions
            savedModSessions = new Dictionary <EverestModule, EverestModuleSession>();
            foreach (EverestModule module in Everest.Modules)
            {
                if (module._Session != null)
                {
                    savedModSessions[module] = module._Session.DeepCloneShared();
                }
            }

            DeepClonerUtils.ClearSharedDeepCloneState();
            return(LoadState(tas));
        }
Beispiel #10
0
 public static void Add(SaveLoadAction saveLoadAction)
 {
     All.Add(saveLoadAction);
 }