Skip to main content

StorySession

Struct StorySession 

Source
pub struct StorySession<R: StoryRng = FastRng> { /* private fields */ }
Expand description

A journaling, replayable session wrapping a Story.

Owns a Story + a SessionJournal. Stepping mirrors Story::advance_with exactly (StepOutcome), recording inputs at the session boundary. The wrapped story is reachable via story / story_mut for the documented journal-bypass escape hatch.

Implementations§

Source§

impl<R: StoryRng> StorySession<R>

Source

pub fn new(story: Story<R>, seed: Option<u64>) -> Self

Wrap story in a fresh session. seed is advisory metadata recorded in the journal (the host is responsible for actually seeding the story via Story::set_rng_seed before/at start).

Source

pub fn journal(&self) -> &SessionJournal

Read-only access to the journal (for export / persistence).

Source

pub fn export_journal(&mut self) -> SessionJournal

Take the journal by value, refreshing its checkpoint first so the exported artifact can fast-restore. The session keeps a fresh empty journal bound to the same program (rarely needed; export usually clones via journal).

Source

pub fn story(&self) -> &Story<R>

Escape hatch: the wrapped story. Reads through here never touch the journal (they can’t mutate anyway).

Source

pub fn story_mut(&mut self) -> &mut Story<R>

Escape hatch: mutable access to the wrapped story. Anything done here bypasses the journal — the documented journal-bypass contract. Use for foreign / shared flows (#200) whose externals never journal.

Source

pub fn advance(&mut self) -> Result<StepOutcome, RuntimeError>

Advance one step with the default (fallback) handler, journaling any inline-resolved externals. Surfaces a deferred external as StepOutcome::AwaitingExternal.

Source

pub fn advance_with( &mut self, handler: &dyn ExternalFnHandler, ) -> Result<StepOutcome, RuntimeError>

Advance one step with a custom handler, journaling any inline-resolved externals it produces (the journaling-window gate: only this frame’s externals record).

Source

pub fn continue_single(&mut self) -> Result<Line, RuntimeError>

Advance until one line of content or a yield point, journaling externals.

Source

pub fn continue_to_pause(&mut self) -> Result<Vec<Line>, RuntimeError>

Advance to the next pause, journaling externals. The last line is always terminal (Done / Choices / End).

Source

pub fn choose(&mut self, index: usize) -> Result<(), RuntimeError>

Select a choice, journaling the Choice event (with its advisory label).

Source

pub fn resolve_external(&mut self, value: Value)

Resolve a deferred external (out-of-band, ExternalResult::Pending), journaling it as an External event. This is the journaling-window gate in action: the session records here because it is the session’s own pause that is being resolved.

Source

pub fn has_pending_external(&self) -> bool

Whether the session is parked on a deferred external.

Source

pub fn set_var( &mut self, name: &str, value: Value, ) -> Result<bool, SessionError>

Set a global variable. Turn-boundary only: rejected mid-turn.

§Errors

SessionError::MutationMidTurn if the session is mid-turn (status Active).

Source

pub fn go_to_path( &mut self, path: &str, args: &[Value], ) -> Result<(), SessionError>

Move the play head to a path (ink ChoosePathString). Turn-boundary only: rejected mid-turn.

§Errors

SessionError::MutationMidTurn mid-turn; wrapped RuntimeErrors from the jump.

Source

pub fn load_state(&mut self, state: &SaveState) -> Result<(), SessionError>

Load a durable SaveState. Turn-boundary only: rejected mid-turn.

§Errors

SessionError::MutationMidTurn mid-turn.

Source

pub fn save_state(&self) -> SaveState

Capture the current durable game state (does not journal).

Source

pub fn call_function( &mut self, name: &str, args: &[Value], handler: &dyn ExternalFnHandler, ) -> Result<Value, RuntimeError>

Evaluate an ink function from engine code, journaling a Call event. The function’s own externals resolve through the isolated (non-journaling) Story::call_function handler path — only the top-level call journals.

§Errors

Wrapped RuntimeErrors from evaluation.

Source

pub fn snapshot(&self) -> StateSnapshot

A typed snapshot of the current game state (globals with list membership, turn counts, callstack summary). See StateSnapshot.

Source

pub fn diff(a: &StateSnapshot, b: &StateSnapshot) -> StateDiff

Pure diff of two snapshots (convenience; see the free diff fn).

Source§

impl<R: StoryRng> StorySession<R>

Source

pub fn restore( story: Story<R>, journal: SessionJournal, ) -> Result<(Self, ReplayOutcome), SessionError>

Fast-restore: apply a journal’s embedded checkpoint and skip replay when the program checksum matches; otherwise fall back to a full replay.

Returns the constructed session and the ReplayOutcome. On a checksum match with a present checkpoint the outcome is ReplayOutcome::Replayed with no warnings (no stepping occurred).

§Errors

SessionError::ChecksumMismatch only if the checksum differs and no checkpoint is present to restore from (nothing safe to do).

Source

pub fn replay( story: Story<R>, journal: &SessionJournal, mode: ExternalReplayMode, live_handler: Option<&dyn ExternalFnHandler>, ) -> (Self, ReplayOutcome)

Replay a journal against story from a fresh start. Consumes the journal prefix event-by-event; on divergence, truncates the journal at that point and parks at the reached position.

The session re-records as it replays, rebuilding its own journal. In ExternalReplayMode::Recorded, the rebuilt prefix is the source prefix: source External events are re-pushed verbatim, including any the re-run did not actually consume (a recorded-mode mismatch falls back to the ink fallback body rather than diverging) — the truncated prefix is the source’s record, not a re-observed trace. In ExternalReplayMode::Live the rebuilt journal is a re-observed trace: live results are journaled as they resolve and source External events are not copied.

mode selects recorded (journal-served) vs live externals. Live replay hitting a deferred external parks with FailReason::AwaitingExternal, retaining the un-replayed tail: resolve the external (resolve_external) and resume with continue_replay, which picks up the remaining recorded inputs from the park point.

Source

pub fn has_pending_replay(&self) -> bool

Whether a parked replay tail is pending (a live replay hit a deferred external). Resolve it and call continue_replay.

Source

pub fn continue_replay( &mut self, live_handler: Option<&dyn ExternalFnHandler>, ) -> ReplayOutcome

Resume a replay parked on a deferred external (FailReason::AwaitingExternal). Resolve the pending external first (via resolve_external), then call this: the session resumes consuming the retained journal tail from the park point — it can complete (ReplayOutcome::Replayed with all warnings accumulated across parks), park again, diverge later, or fail.

With no pending replay tail this keeps the advance-only behavior: it steps the live story to its next pause with live_handler (journaling externals as in normal play) and returns Replayed on reaching the pause, or Failed if it parks or errors (at_event is then the rebuilt journal’s current length, where the next event would land).

Auto Trait Implementations§

§

impl<R = FastRng> !RefUnwindSafe for StorySession<R>

§

impl<R = FastRng> !Send for StorySession<R>

§

impl<R = FastRng> !Sync for StorySession<R>

§

impl<R = FastRng> !UnwindSafe for StorySession<R>

§

impl<R> Freeze for StorySession<R>

§

impl<R> Unpin for StorySession<R>
where R: Unpin,

§

impl<R> UnsafeUnpin for StorySession<R>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.