Skip to content

Commit 80c4e59

Browse files
authored
Merge pull request #884 from AlexKnauth/segment-splitted-3
Add timer_current_split_index and timer_segment_splitted
2 parents f4e390e + ff1a381 commit 80c4e59

6 files changed

Lines changed: 101 additions & 1 deletion

File tree

crates/livesplit-auto-splitting/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,18 @@ impl MemoryRangeFlags {
9999
unsafe extern "C" {
100100
/// Gets the state that the timer currently is in.
101101
pub safe fn timer_get_state() -> TimerState;
102+
/// Accesses the index of the split the attempt is currently on.
103+
/// If there's no attempt in progress, `-1` is returned instead.
104+
/// This returns an index that is equal to the amount of segments
105+
/// when the attempt is finished, but has not been reset.
106+
/// So you need to be careful when using this value for indexing.
107+
/// Same index does not imply same split on undo and then split.
108+
pub safe fn timer_current_split_index() -> i64;
109+
/// Whether the segment at `idx` was splitted this attempt.
110+
/// Returns `1` if the segment was splitted, or `0` if skipped.
111+
/// If `idx` is greater than or equal to the current split index,
112+
/// `-1` is returned instead.
113+
pub safe fn timer_segment_splitted(idx: u64) -> i32;
102114

103115
/// Starts the timer.
104116
pub safe fn timer_start();

crates/livesplit-auto-splitting/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,18 @@
9999
//! unsafe extern "C" {
100100
//! /// Gets the state that the timer currently is in.
101101
//! pub safe fn timer_get_state() -> TimerState;
102+
//! /// Accesses the index of the split the attempt is currently on.
103+
//! /// If there's no attempt in progress, `-1` is returned instead.
104+
//! /// This returns an index that is equal to the amount of segments
105+
//! /// when the attempt is finished, but has not been reset.
106+
//! /// So you need to be careful when using this value for indexing.
107+
//! /// Same index does not imply same split on undo and then split.
108+
//! pub safe fn timer_current_split_index() -> i64;
109+
//! /// Whether the segment at `idx` was splitted this attempt.
110+
//! /// Returns `1` if the segment was splitted, or `0` if skipped.
111+
//! /// If `idx` is greater than or equal to the current split index,
112+
//! /// `-1` is returned instead.
113+
//! pub safe fn timer_segment_splitted(idx: u64) -> i32;
102114
//!
103115
//! /// Starts the timer.
104116
//! pub safe fn timer_start();

crates/livesplit-auto-splitting/src/runtime/api/timer.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use anyhow::Result;
22
use wasmtime::{Caller, Linker};
33

4-
use crate::{runtime::Context, CreationError, Timer};
4+
use crate::{CreationError, Timer, runtime::Context};
55

66
use super::{get_str, memory_and_context};
77

@@ -14,6 +14,32 @@ pub fn bind<T: Timer>(linker: &mut Linker<Context<T>>) -> Result<(), CreationErr
1414
source,
1515
name: "timer_get_state",
1616
})?
17+
.func_wrap("env", "timer_current_split_index", {
18+
|caller: Caller<'_, Context<T>>| {
19+
caller
20+
.data()
21+
.timer
22+
.current_split_index()
23+
.map_or(-1, |i| i as i64)
24+
}
25+
})
26+
.map_err(|source| CreationError::LinkFunction {
27+
source,
28+
name: "timer_current_split_index",
29+
})?
30+
.func_wrap("env", "timer_segment_splitted", {
31+
|caller: Caller<'_, Context<T>>, index: u64| {
32+
Ok(caller
33+
.data()
34+
.timer
35+
.segment_splitted(index as usize)
36+
.map_or(-1, |b| b as i32))
37+
}
38+
})
39+
.map_err(|source| CreationError::LinkFunction {
40+
source,
41+
name: "timer_segment_splitted",
42+
})?
1743
.func_wrap(
1844
"env",
1945
"timer_start",

crates/livesplit-auto-splitting/src/timer.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ pub enum LogLevel {
3535
pub trait Timer: Send {
3636
/// Returns the current state of the timer.
3737
fn state(&self) -> TimerState;
38+
/// Accesses the index of the split the attempt is currently on.
39+
/// If there's no attempt in progress, `None` is returned instead.
40+
/// This returns an index that is equal to the amount of segments
41+
/// when the attempt is finished, but has not been reset.
42+
/// So you need to be careful when using this value for indexing.
43+
/// Same index does not imply same split on undo and then split.
44+
fn current_split_index(&self) -> Option<usize>;
45+
/// Whether the segment at `idx` was splitted this attempt.
46+
/// Returns `Some(true)` if the segment was splitted,
47+
/// or `Some(false)` if skipped.
48+
/// If `idx` is greater than or equal to the current split index,
49+
/// `None` is returned instead.
50+
fn segment_splitted(&self, idx: usize) -> Option<bool>;
3851
/// Starts the timer.
3952
fn start(&mut self);
4053
/// Splits the current segment.

crates/livesplit-auto-splitting/tests/sandboxing.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ impl Timer for DummyTimer {
1414
fn state(&self) -> TimerState {
1515
TimerState::NotRunning
1616
}
17+
fn current_split_index(&self) -> Option<usize> {
18+
None
19+
}
20+
fn segment_splitted(&self, _idx: usize) -> Option<bool> {
21+
None
22+
}
1723
fn start(&mut self) {}
1824
fn split(&mut self) {}
1925
fn skip_split(&mut self) {}

src/auto_splitting/mod.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,18 @@
9999
//! unsafe extern "C" {
100100
//! /// Gets the state that the timer currently is in.
101101
//! pub safe fn timer_get_state() -> TimerState;
102+
//! /// Accesses the index of the split the attempt is currently on.
103+
//! /// If there's no attempt in progress, `-1` is returned instead.
104+
//! /// This returns an index that is equal to the amount of segments
105+
//! /// when the attempt is finished, but has not been reset.
106+
//! /// So you need to be careful when using this value for indexing.
107+
//! /// Same index does not imply same split on undo and then split.
108+
//! pub safe fn timer_current_split_index() -> i64;
109+
//! /// Whether the segment at `idx` was splitted this attempt.
110+
//! /// Returns `1` if the segment was splitted, or `0` if skipped.
111+
//! /// If `idx` is greater than or equal to the current split index,
112+
//! /// `-1` is returned instead.
113+
//! pub safe fn timer_segment_splitted(idx: u64) -> i32;
102114
//!
103115
//! /// Starts the timer.
104116
//! pub safe fn timer_start();
@@ -787,6 +799,25 @@ impl<E: event::CommandSink + TimerQuery + Send> AutoSplitTimer for Timer<E> {
787799
}
788800
}
789801

802+
fn current_split_index(&self) -> Option<usize> {
803+
self.0.get_timer().current_split_index()
804+
}
805+
806+
fn segment_splitted(&self, idx: usize) -> Option<bool> {
807+
let t = self.0.get_timer();
808+
if !(idx < t.current_split_index()?) {
809+
return None;
810+
}
811+
Some(
812+
t.run()
813+
.segments()
814+
.get(idx)?
815+
.split_time()
816+
.real_time
817+
.is_some(),
818+
)
819+
}
820+
790821
fn start(&mut self) {
791822
drop(self.0.start());
792823
}

0 commit comments

Comments
 (0)