public override void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { state.IsGameTimePaused = true; bool start = false; lock (eventsLock) { foreach (var ev in events) { if (ev is GameEndEvent) { if (state.CurrentPhase == TimerPhase.Running && settings.ShouldSplitOnGameEnd()) { state.SetGameTime(ev.Time); model.Split(); } } else if (ev is MapChangeEvent) { var e = (MapChangeEvent)ev; if (visitedMaps.Add(e.Map) && settings.ShouldSplitOn(e.Map)) { state.SetGameTime(e.Time); model.Split(); } } else if (ev is TimerResetEvent) { if (settings.IsAutoResetEnabled()) { state.SetGameTime(ev.Time); model.Reset(); } } else if (ev is TimerStartEvent) { if (settings.IsAutoStartEnabled()) { state.SetGameTime(ev.Time); start = true; } } } events.Clear(); } if (start) { model.Start(); } TimeSpan curTime; lock (currentTimeLock) { curTime = currentTime; } state.SetGameTime(curTime); }
public override void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { if (state.CurrentPhase == TimerPhase.NotRunning) { if (AutoSplitter.ShouldStart(state)) { Model.Start(); } } else if (state.CurrentPhase == TimerPhase.Running || state.CurrentPhase == TimerPhase.Paused) { if (AutoSplitter.ShouldReset(state)) { Model.Reset(); return; } else if (AutoSplitter.ShouldSplit(state)) { Model.Split(); } state.IsGameTimePaused = AutoSplitter.IsGameTimePaused(state); var gameTime = AutoSplitter.GetGameTime(state); if (gameTime != null) { state.SetGameTime(gameTime); } } }
// This is executed repeatedly as long as the game is connected and initialized. private void DoUpdate(LiveSplitState state) { OldState = State.RefreshValues(_game); if (!(RunMethod(_methods.update, state) ?? true)) { // If Update explicitly returns false, don't run anything else return; } // Call the start segment if the splits are not running, but ensure that the segment is called at least once. if (state.CurrentPhase == TimerPhase.NotRunning || !startMethodCalledFromUpdate) { if (RunMethod(_methods.start, state) ?? false) { if (_settings.GetBasicSettingValue("start") && state.CurrentPhase == TimerPhase.NotRunning) { _timer.Start(); } } startMethodCalledFromUpdate = true; } if (state.CurrentPhase == TimerPhase.Running || state.CurrentPhase == TimerPhase.Paused) { if (_uses_game_time && !state.IsGameTimeInitialized) { _timer.InitializeGameTime(); } var is_paused = RunMethod(_methods.isLoading, state); if (is_paused != null) { state.IsGameTimePaused = is_paused; } var game_time = RunMethod(_methods.gameTime, state); if (game_time != null) { state.SetGameTime(game_time); } if (RunMethod(_methods.reset, state) ?? false) { if (_settings.GetBasicSettingValue("reset")) { _timer.Reset(); } } else if (RunMethod(_methods.split, state) ?? false) { if (_settings.GetBasicSettingValue("split")) { _timer.Split(); } } } }
void gameMemory_OnTick(object sender, uint ticks) { if (_state.CurrentPhase == TimerPhase.Running) { TimerTicks += ticks; _state.SetGameTime(TimeSpan.FromSeconds((float)TimerTicks / (float)60)); //Debug.WriteLine("OnTick: GameTime changed to: " + _state.CurrentTime.GameTime + " | Added " + ticks + " ticks | Total ticks " + TimerTicks + " - " + _gameMemory.frameCounter); } }
public void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { // hack to prevent flicker, doesn't actually pause anything state.IsGameTimePaused = true; // Update is called every 25ms, so up to 25ms IGT can be lost if using delay and no auto-start if (_waitingForDelay) { if (state.CurrentTime.RealTime >= TimeSpan.Zero) { _sessionTicksOffset = _sessionTicks; _waitingForDelay = false; } else { state.SetGameTime(state.CurrentTime.RealTime); } } if (!_waitingForDelay) { // update game time, don't show negative time due to tick adjusting state.SetGameTime(this.GameTime >= TimeSpan.Zero ? this.GameTime : TimeSpan.Zero); } if (!this.Settings.ShowGameTime) { return; } this.InternalComponent.TimeValue = state.CurrentTime[state.CurrentTimingMethod == TimingMethod.GameTime ? TimingMethod.RealTime : TimingMethod.GameTime]; this.InternalComponent.InformationName = state.CurrentTimingMethod == TimingMethod.GameTime ? "Real Time" : "Game Time"; _cache.Restart(); _cache["TimeValue"] = this.InternalComponent.ValueLabel.Text; _cache["TimingMethod"] = state.CurrentTimingMethod; if (invalidator != null && _cache.HasChanged) { invalidator.Invalidate(0f, 0f, width, height); } }
public void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { if (state.CurrentPhase == TimerPhase.Ended) { state.SetGameTime(_endTime.HasValue ? _endTime.Value : TimeSpan.Zero); } else { if (state.CurrentTime.RealTime >= TimeSpan.Zero) { // Update is called every 25ms, so up to 25ms can be lost if using delay if (_waitingForDelay) { _removeTime = _mapTime; _waitingForDelay = false; } state.SetGameTime(state.CurrentPhase == TimerPhase.Running || state.CurrentPhase == TimerPhase.Paused ? this.GameTime : TimeSpan.Zero); } } if (!this.Settings.ShowGameTime) { return; } this.InternalComponent.TimeValue = state.CurrentTime[state.CurrentTimingMethod == TimingMethod.GameTime ? TimingMethod.RealTime : TimingMethod.GameTime]; this.InternalComponent.InformationName = state.CurrentTimingMethod == TimingMethod.GameTime ? "Real Time" : "Game Time"; _cache.Restart(); _cache["TimeValue"] = this.InternalComponent.ValueLabel.Text; _cache["TimingMethod"] = state.CurrentTimingMethod; if (invalidator != null && _cache.HasChanged) { invalidator.Invalidate(0f, 0f, width, height); } }
// This is always called while the component is added to your LiveSplit layout. public override void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { _gm.ILsettings = compSettings.ilMode; _gm.Update(); if (state.CurrentPhase == TimerPhase.Running) { state.SetGameTime(new TimeSpan(0, 0, 0, _gm.gameTime, 0)); } }
void DoSplit() { // make split times accurate _state.SetGameTime(this.GameTime); bool before = _state.Settings.DoubleTapPrevention; _state.Settings.DoubleTapPrevention = false; _timer.Split(); _state.Settings.DoubleTapPrevention = before; }
public virtual void Update(LiveSplitState state) { emulator.Update(state); if (!state.IsGameTimeInitialized) { timer.CurrentState = state; timer.InitializeGameTime(); } state.SetGameTime(GameTime(state)); }
public override void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { gameData.Update(state); if (state.IsGameTimeInitialized) { timer.InitializeGameTime(); } if (state.CurrentPhase == TimerPhase.Running) { state.SetGameTime(gameData.GameTime); } }
public void Update(LiveSplitState lsState) { if (Emulator != null && !Emulator.Process.HasExited) { OldState = State.RefreshValues(); if (lsState.CurrentPhase == TimerPhase.NotRunning) { if (Start(lsState, OldState.Data, State.Data)) { Model.Start(); } } else if (lsState.CurrentPhase == TimerPhase.Running || lsState.CurrentPhase == TimerPhase.Paused) { if (Reset(lsState, OldState.Data, State.Data)) { Model.Reset(); return; } else if (Split(lsState, OldState.Data, State.Data)) { Model.Split(); } var isPaused = IsPaused(lsState, OldState.Data, State.Data); if (isPaused != null) { lsState.IsGameTimePaused = isPaused; } var encounter = GetEncounter(lsState, OldState.Data, State.Data); var gameTime = GameTime(lsState, OldState.Data, State.Data); if (gameTime != null) { lsState.SetGameTime(gameTime); } } } else { if (Model == null) { Model = new TimerModel() { CurrentState = lsState }; } TryConnect(); } }
public void Update(LiveSplitState lsState) { if (Game != null && !Game.HasExited) { OldState = State.RefreshValues(Game); if (lsState.CurrentPhase == TimerPhase.NotRunning) { if (Start.Run(lsState, OldState, State) ?? false) { Model.Start(); } } else if (lsState.CurrentPhase == TimerPhase.Running || lsState.CurrentPhase == TimerPhase.Paused) { if (Reset.Run(lsState, OldState, State) ?? false) { Model.Reset(); return; } else if (Split.Run(lsState, OldState, State) ?? false) { Model.Split(); } var isPaused = IsLoading.Run(lsState, OldState, State); if (isPaused != null) { lsState.IsGameTimePaused = isPaused; } var gameTime = GameTime.Run(lsState, OldState, State); if (gameTime != null) { lsState.SetGameTime(gameTime); } } } else { if (Model == null) { Model = new TimerModel() { CurrentState = lsState }; } TryConnect(); } }
public override void Update(UI.IInvalidator invalidator, LiveSplitState lsState, float width, float height, UI.LayoutMode mode) { if (Game != null && !Game.HasExited) { OldState = State.RefreshValues(); if (lsState.CurrentPhase == TimerPhase.NotRunning) { if (Start(lsState, OldState.Data, State.Data)) { Model.Start(); } } else if (lsState.CurrentPhase == TimerPhase.Running || lsState.CurrentPhase == TimerPhase.Paused) { if (Reset(lsState, OldState.Data, State.Data)) { Model.Reset(); return; } else if (Split(lsState, OldState.Data, State.Data)) { Model.Split(); } var isPaused = IsPaused(lsState, OldState.Data, State.Data); lsState.IsGameTimePaused = isPaused; var gameTime = GameTime(lsState, OldState.Data, State.Data); if (gameTime != null) { lsState.SetGameTime(gameTime); } } } else { if (Model == null) { Model = new TimerModel() { CurrentState = lsState }; } TryConnect(); } }
private void UpdateGameTime(int newGameTime) { // When the player quits the game, the IGT clock keeps ticking for 18 extra frames. Those frames are // removed from the timer on quitout. This is largely done to keep parity with the existing IGT tool. const int QuitoutCorrection = 594; LiveSplitState state = timer.CurrentState; // Setting this value to always be true prevents a weird timer creep from LiveSplit. I don't know why. state.IsGameTimePaused = true; TimerPhase phase = timer.CurrentState.CurrentPhase; int previousTime = run.GameTime; // This condition is only possible during a run when game time isn't increasing (game time resets to // zero on the main menu). bool quitout = newGameTime == 0 && previousTime > 0; // Previously, the timer was actually paused and unpaused here (rather than just putting game time in // stasis temporarily). I found that constant pausing and unpausing distracting, so I removed it. if (quitout) { switch (phase) { case TimerPhase.Running: run.MaxGameTime -= QuitoutCorrection; break; case TimerPhase.NotRunning: run.MaxGameTime = 0; break; } } int max = Math.Max(newGameTime, run.MaxGameTime); if (phase != TimerPhase.Paused) { state.SetGameTime(TimeSpan.FromMilliseconds(max)); } run.GameTime = newGameTime; run.MaxGameTime = max; }
public void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { int millis = _pointer.GetIgt(); //Native.GetGameTimeMilliseconds(addr, p.Id.GetHandle(), 8); if (millis > 100) { _oldMillis = millis; _latch = false; } if (millis == 0 && !_latch) { _oldMillis -= 594; _latch = true; } if (_oldMillis <= 0) { _oldMillis = 0; } state.SetGameTime(new TimeSpan(0, 0, 0, 0, _oldMillis <= 1 ? 1 : _oldMillis)); }
public void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { int millis = Pointer.GetIgt(); //Native.GetGameTimeMilliseconds(addr, p.Id.GetHandle(), 8); if (millis > 100) { _oldMillis = millis; _latch = false; } if (millis == 0 && !_latch) { _oldMillis -= 594; _latch = true; } if (_oldMillis <= 0) { _oldMillis = 0; } state.SetGameTime(new TimeSpan(0, 0, 0, 0, _oldMillis <= 1 ? 1 : _oldMillis)); //autostart timer. Might be worth changing this to something based on some memory flag if (_control.cb_autoStartTimer.Checked && millis > 0 && millis < 500) { if (state.CurrentPhase == TimerPhase.NotRunning) { TimerModel timer = new TimerModel(); timer.CurrentState = state; timer.Start(); } } //autosplit if (_control.cb_autoSplit.Checked) { _splitter.AttemptSplit(); } }
public override void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { state.SetGameTime(new TimeSpan(0, 0, 0, 0, instance.IGT)); if (instance.Autosplit) { int difference = instance.SplitIndex - state.CurrentSplitIndex; while (difference > 1) { Model.SkipSplit(); difference--; } if (difference == 1) { Model.Split(); } if (instance.SplitIndex == 0 && state.CurrentSplitIndex > 0) { Model.Reset(); Model.Start(); } } }
public void Update() { _oldMemoryState = _currentMemoryState; _currentMemoryState = Memory.GetState(); switch (_state.CurrentPhase) { case TimerPhase.NotRunning: if (ShouldStart()) { _startingMemoryState = _currentMemoryState; // Temporarily adjust the start offset for real-time accuracy. var userOffset = _state.Run.Offset; _state.Run.Offset = DateTime.Now - _firstLoadStartTime + TimeSpan.FromSeconds(StartOffset[AutosplitterSettings.StartCondition]); _model.Start(); _state.Run.Offset = userOffset; _state.SetGameTime(TimeSpan.FromSeconds(StartOffset[AutosplitterSettings.StartCondition])); } break; case TimerPhase.Running: // Pause timer when loading _state.IsGameTimePaused = _currentMemoryState.IsLoading; if (DateTime.Now > _timeUntilNextSplit && ShouldSplit()) { _model.Split(); } else if (ShouldReset()) { _model.Reset(); } break; } }
public override void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { gameProcess.Update(); state.SetGameTime(new TimeSpan(0, 0, 0, 0, dsigt.IGT)); }
public void Update(LiveSplitState state) { // Hopefully get our process from the memory, as well as initialize our MemoryDefinition for reading if (gameProcess == null || gameProcess.HasExited || versionDefinition == null) { if (!this.TryGetGameProcess(state)) { return; } } // No need to evaluate anything if not running if (state.CurrentPhase != TimerPhase.Running) { return; } versionDefinition.UpdateAll(gameProcess); if ((versionDefinition.isLoadingState?.Changed ?? false) || (versionDefinition.isMainMenuState?.Changed ?? false) || (versionDefinition.levelSplitsState?.Changed ?? false) || initalUpdate) { bool bPauseTimer = false; Debug.WriteLine("State changed..."); if (versionDefinition.isLoadingState != null) { bool pauses = versionDefinition.isLoadingInfo.ShouldPauseOnValue(versionDefinition.isLoadingState.Current); bPauseTimer |= pauses; int currentValue = versionDefinition.isLoadingState.Current; int wantedValue = versionDefinition.isLoadingInfo.value; Debug.WriteLine(string.Format( "Loading: 0x{0:X} {1} 0x{2:X}, should{3} pause", currentValue, currentValue == wantedValue ? "==" : "!=", wantedValue, pauses ? "" : "n't" )); } if (versionDefinition.isMainMenuState != null) { bool pauses = versionDefinition.isMainMenuInfo.ShouldPauseOnValue(versionDefinition.isMainMenuState.Current); bPauseTimer |= pauses; int currentValue = versionDefinition.isMainMenuState.Current; int wantedValue = versionDefinition.isMainMenuInfo.value; Debug.WriteLine(string.Format( "Main Menu: 0x{0:X} {1} 0x{2:X}, should{3} pause", currentValue, currentValue == wantedValue ? "==" : "!=", wantedValue, pauses ? "" : "n't" )); } if (versionDefinition.levelSplitsState != null) { int currentLevel = versionDefinition.levelSplitsState.Current; // lastLevel will not update to the main menu, so this might be different int oldLevel = versionDefinition.levelSplitsState.Old; int mainMenu = versionDefinition.levelSplitsInfo.value; if (initalUpdate) { lastLevel = currentLevel; } else if (currentLevel != 0 && currentLevel != oldLevel) // Filter out invalid pointers and unchanged values { // If you switched to the main menu, add a sq if (currentLevel == mainMenu) { CounterHandler.Increment(state); } // If you switched to a different level than the stored last level, split else if (currentLevel != lastLevel && settings.AllowLevelSplits) { Debug.WriteLine($"Level changed from 0x{lastLevel:X} to 0x{currentLevel:X}"); timerModel.Split(); lastLevel = currentLevel; } } } state.IsGameTimePaused = bPauseTimer; if (initalUpdate) { if (bPauseTimer && !state.IsGameTimeInitialized) { state.SetGameTime(TimeSpan.Zero); } state.IsGameTimeInitialized = true; } initalUpdate = false; } }
public virtual void Update(LiveSplitState state, TimerModel timer) { if (!game.Attach()) { return; } switch (state.CurrentPhase) { case TimerPhase.NotRunning: if (StartTimer()) { timer.Start(); } return; case TimerPhase.Running: case TimerPhase.Paused: if (ProvidesGameTime) { TimeSpan?igt = GameTime(); if (!state.IsGameTimeInitialized) { timer.InitializeGameTime(); } state.IsGameTimePaused = true; state.SetGameTime(igt); } while (true) { var cursplit = state.CurrentSplitIndex; if (cursplit <= lastsplit || cursplit >= state.Run.Count) { return; } Match m = split_regex.Match(state.Run[cursplit].Name); string splitname = m.Success ? m.Groups[2].Value.Normalize().ToLowerInvariant() : ""; if (!splits.ContainsKey(splitname)) { timer.SkipSplit(); } else if (intsplits[splits[splitname]]()) { if (DateTime.UtcNow - lastsplitat < TimeSpan.FromMilliseconds(100)) { timer.SkipSplit(); } else { timer.Split(); } } else { return; } lastsplitat = DateTime.UtcNow; lastsplit = cursplit; } } }
private void DoUpdate(LiveSplitState state, DeltaOutput d) { var updateState = RunMethod(Methods.update, state, d); // If Update explicitly returns false, don't run anything else if (updateState is bool && updateState == false) { return; } var offsetTime = TimeStamp.CurrentDateTime.Time - d.History[d.FrameIndex].FrameEnd; // Enable regardless to keep track of offseting for now. if (!state.IsGameTimeInitialized) { Timer.InitializeGameTime(); } if (state.CurrentPhase == TimerPhase.Running || state.CurrentPhase == TimerPhase.Paused) { if (UsesGameTime) { if (UsesIsLoading) { var isPausedState = RunMethod(Methods.isLoading, state, d); if (isPausedState is bool) { var prevPauseState = state.IsGameTimePaused; state.IsGameTimePaused = isPausedState; if (prevPauseState != isPausedState) { if (isPausedState) { state.GameTimePauseTime -= offsetTime; } else { state.GameTimePauseTime += offsetTime; } } } } if (UsesGameTime) { var gameTimeState = RunMethod(Methods.gameTime, state, d); if (gameTimeState is TimeSpan) { state.SetGameTime(gameTimeState); } } } if (Settings.GetBasicSettingValue("reset")) { var resetState = RunMethod(Methods.reset, state, d); if (resetState is bool && resetState == true) { Timer.Reset(); } } if (Settings.GetBasicSettingValue("split")) { var splitState = RunMethod(Methods.split, state, d); if (splitState is bool && splitState == true) { splitState = TimeSpan.Zero; } if (splitState is TimeSpan) { AdjustGameTime(state, splitState.Negate()); if (!UsesCustomGameTime) { AdjustGameTime(state, offsetTime.Negate()); } Timer.Split(); if (state.CurrentPhase != TimerPhase.Ended) { AdjustGameTime(state, splitState); if (!UsesCustomGameTime) { AdjustGameTime(state, offsetTime); } } else { LastSplitOffset = splitState; if (!UsesCustomGameTime) { LastSplitOffset += offsetTime; } } } } // @TODO: Add undo and skip; } else if (state.CurrentPhase == TimerPhase.NotRunning && Settings.GetBasicSettingValue("start")) { var startState = RunMethod(Methods.start, state, d); if ((startState is bool && startState == true) || startState is TimeSpan) { Timer.Start(); if (!state.IsGameTimeInitialized) { Timer.InitializeGameTime(); } LastSplitOffset = TimeSpan.Zero; TimeSpan startOffset = (startState is TimeSpan) ? startState : TimeSpan.Zero; AdjustGameTime(state, startOffset); if (!UsesCustomGameTime) { AdjustGameTime(state, offsetTime); } } } PreviousPhase = state.CurrentPhase; }
public void Update(LiveSplitState state) { // Hopefully get our process from the memory, as well as initialize our MemoryDefinition for reading if (gameProcess == null || gameProcess.HasExited || versionDefinition == null) { if (!this.TryGetGameProcess(state)) { return; } } // No need to evaluate anything if not running, paused, or ended if (state.CurrentPhase != TimerPhase.Running) { initalUpdate = true; return; } versionDefinition.UpdateAll(gameProcess); if ((versionDefinition.isLoadingState?.Changed ?? false) || (versionDefinition.isMainMenuState?.Changed ?? false) || (versionDefinition.levelSplitsState?.Changed ?? false) || initalUpdate) { bool bPauseTimer = false; Debug.WriteLine("State changed..."); if (versionDefinition.isLoadingState != null) { bool pauses = versionDefinition.isLoadingInfo.ShouldPauseOnValue(versionDefinition.isLoadingState.Current); bPauseTimer |= pauses; int currentValue = versionDefinition.isLoadingState.Current; int wantedValue = versionDefinition.isLoadingInfo.value; Debug.WriteLine(string.Format( "Loading: 0x{0:X} {1} 0x{2:X}, should{3} pause", currentValue, currentValue == wantedValue ? "==" : "!=", wantedValue, pauses ? "" : "n't" )); } if (versionDefinition.isMainMenuState != null) { bool pauses = versionDefinition.isMainMenuInfo.ShouldPauseOnValue(versionDefinition.isMainMenuState.Current); bPauseTimer |= pauses; int currentValue = versionDefinition.isMainMenuState.Current; int wantedValue = versionDefinition.isMainMenuInfo.value; Debug.WriteLine(string.Format( "Main Menu: 0x{0:X} {1} 0x{2:X}, should{3} pause", currentValue, currentValue == wantedValue ? "==" : "!=", wantedValue, pauses ? "" : "n't" )); } if (versionDefinition.levelSplitsState != null && settings.AllowLevelSplits) { int currentLevel = versionDefinition.levelSplitsState.Current; if (initalUpdate) { lastLevel = currentLevel; } else if (currentLevel != lastLevel && currentLevel != 0 && // Filter out invalid pointers currentLevel != versionDefinition.levelSplitsInfo.value) // Filter out main menu { Debug.WriteLine($"Level changed from 0x{lastLevel:X} to 0x{currentLevel:X}"); timerModel.Split(); lastLevel = currentLevel; } } state.IsGameTimePaused = bPauseTimer; if (initalUpdate) { // We also get here if you just unpaused, so only do this if not initalized if (bPauseTimer && !state.IsGameTimeInitialized) { state.SetGameTime(TimeSpan.Zero); } state.IsGameTimeInitialized = true; } initalUpdate = false; } }
private void AdjustGameTime(LiveSplitState state, TimeSpan offsetTime) { state.SetGameTime(state.CurrentTime.GameTime + offsetTime); }
public void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { // hack to prevent flicker, doesn't actually pause anything state.IsGameTimePaused = true; // Update is called every 25ms, so up to 25ms IGT can be lost if using delay and no auto-start if (_waitingForDelay) { if (state.CurrentTime.RealTime >= TimeSpan.Zero) { _sessionTicksOffset = _sessionTicks; _waitingForDelay = false; } else { state.SetGameTime(state.CurrentTime.RealTime); } } if (!_waitingForDelay) { // update game time, don't show negative time due to tick adjusting state.SetGameTime(this.GameTime >= TimeSpan.Zero ? this.GameTime : TimeSpan.Zero); } AltTimingComponent.Enabled = Settings.ShowGameTime.Value; TickCountComponent.Enabled = Settings.ShowTickCount.Value; _componentRenderer.Update(invalidator, state, width, height, mode); if (_componentRenderer.VisibleComponents.Any()) { _cache.Restart(); if (this.Settings.ShowGameTime.Value) { // change this if we ever have new timing methods TimingMethod method = state.CurrentTimingMethod; if (Settings.ShowAltTime.Value) { method = (TimingMethod)(((int)method + 1) % 2); } this.AltTimingComponent.SetText(state.CurrentTime[method], Settings.GameTimeDecimalPlaces.Value); this.AltTimingComponent.SetName(method == TimingMethod.RealTime ? "Real Time" : "Game Time"); _cache["TimeValue"] = this.AltTimingComponent.Component.ValueLabel.Text; _cache["TimingMethod"] = state.CurrentTimingMethod; } if (this.Settings.ShowTickCount.Value) { TickCountComponent.SetText(((long)(GameTime.TotalSeconds / _intervalPerTick)).ToString()); _cache["TickCount"] = this.TickCountComponent.Component.ValueLabel.Text; } if (_cache.HasChanged) { invalidator?.Invalidate(0f, 0f, width, height); } } #if DEBUG if (_prevGameTime <= GameTime) { _prevGameTime = GameTime; } else { Debug.WriteLine($"game time sunk mid run" + $"\n\ntotal ticks: {_totalTicks}\nsession ticks: {_sessionTicks}\n\n" + $"game time now: {GameTime}\ngame time then: {_prevGameTime}"); } #endif }