From fd82dad287d02b6648f0b41187711b9cfb12cc00 Mon Sep 17 00:00:00 2001 From: AlexKnauth Date: Fri, 14 Jun 2024 02:50:09 -0400 Subject: [PATCH] unstable: timer_current_split_index --- Cargo.toml | 3 +++ src/lib.rs | 1 + src/timer.rs | 46 +++++++++++++++++++++++++++++++++++++++++++++- src/unstable.rs | 22 ++++++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/unstable.rs diff --git a/Cargo.toml b/Cargo.toml index 32c9c646..c661e062 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,9 @@ serde_json = { version = "1" } xmltree = { version = "0.10.3" } +[features] +unstable = [] + [lib] crate-type = ["cdylib"] diff --git a/src/lib.rs b/src/lib.rs index 534029c1..9f0a1cbf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ mod legacy_xml; mod settings_gui; mod splits; mod timer; +mod unstable; use asr::future::{next_tick, retry}; use asr::Process; diff --git a/src/timer.rs b/src/timer.rs index 1d072cd1..01cc95ef 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -2,6 +2,8 @@ use asr::timer::TimerState; use serde::{Deserialize, Serialize}; +use crate::unstable::maybe_timer_current_split_index; + pub fn is_timer_state_between_runs(s: TimerState) -> bool { s == TimerState::NotRunning || s == TimerState::Ended } @@ -66,6 +68,13 @@ pub struct Timer { /// [1,n): Running /// n: Ended without knowing auto-reset safe i: usize, + /// The last observed timer_current_split_index. + /// Just in case timer_current_split_index is a tad out-of-date. + /// -2: Unknown + /// -1: NotRunning + /// [0,n-1): Running + /// n-1: Ended + last_split_index: i32, /// Number of autosplits including both start and end. /// One more than the number of segments. n: usize, @@ -84,10 +93,12 @@ impl Resettable for Timer { impl Timer { pub fn new(n: usize, auto_reset: &'static [TimerState]) -> Timer { let asr_state = asr::timer::state(); + let asr_index = maybe_timer_current_split_index(); Timer { state: asr_state, last_state: asr_state, i: 0, + last_split_index: asr_index.unwrap_or(-2), n, auto_reset, } @@ -111,6 +122,12 @@ impl Timer { } pub fn update(&mut self, r: &mut R) { + self.update_state(r); + #[cfg(feature = "unstable")] + self.update_index(); + } + + fn update_state(&mut self, r: &mut R) { let asr_state = asr::timer::state(); if asr_state == self.state || asr_state == self.last_state { self.last_state = asr_state; @@ -146,6 +163,33 @@ impl Timer { self.last_state = asr_state; } + #[cfg(feature = "unstable")] + fn update_index(&mut self) -> Option<()> { + let asr_index = maybe_timer_current_split_index()?; + if asr_index == self.last_split_index + { + return Some(()); + } + let delta = asr_index + 1 - self.i as i32; + if delta == 0 || delta >= self.n as i32 { + return Some(()); + } + match delta { + -1 => asr::print_message("Detected a manual undo."), + 1 => asr::print_message("Detected a manual split or skip."), + d if d.is_negative() => asr::print_message(&format!("Detected a {} manual undos.", -d)), + d if d.is_positive() => asr::print_message(&format!("Detected a {} manual splits or skips.", d)), + _ => (), + } + let new_i = (self.i as i32 + delta) as usize; + if new_i >= self.n && self.is_auto_reset_safe() { + self.i = 0; + } else { + self.i = new_i; + } + Some(()) + } + pub fn action(&mut self, a: SplitterAction, r: &mut R) { match a { SplitterAction::Pass => (), @@ -169,7 +213,7 @@ impl Timer { self.i += 1; } SplitterAction::ManualSplit => { - if 0 < self.i && self.i + 1 < self.n { + if self.last_split_index == -2 && 0 < self.i && self.i + 1 < self.n { self.i += 1; } } diff --git a/src/unstable.rs b/src/unstable.rs new file mode 100644 index 00000000..f8be2e9f --- /dev/null +++ b/src/unstable.rs @@ -0,0 +1,22 @@ + +#[cfg(feature = "unstable")] +extern "C" { + /// Accesses the index of the split the attempt is currently on. If there's + /// no attempt in progress, `-1` is returned instead. This returns an + /// index that is equal to the amount of segments when the attempt is + /// finished, but has not been reset. So you need to be careful when using + /// this value for indexing. + fn timer_current_split_index() -> i32; +} + +/// Accesses the index of the split the attempt is currently on. If there's +/// no attempt in progress, `-1` is returned instead. This returns an +/// index that is equal to the amount of segments when the attempt is +/// finished, but has not been reset. So you need to be careful when using +/// this value for indexing. +pub fn maybe_timer_current_split_index() -> Option { + #[cfg(feature = "unstable")] + return Some(unsafe { timer_current_split_index() }); + #[allow(unreachable_code)] + None +}