turnbase_session/lib.rs
1//! The Session port: submit a request against a running game and get a
2//! response, whether the authoritative state lives in this process or (later)
3//! a remote one.
4//!
5//! A [`Session`] is a client-side handle, not the host itself. Only some
6//! implementations actually hold the authoritative state:
7//!
8//! - [`LocalSession`] owns the [`turnbase::Game`] and its state directly and
9//! mutates it in process. This process *is* the host for as long as the
10//! value lives. Zero I/O; this is what tests, a long-lived server, and
11//! self-play hold onto.
12//! - [`FileSession`] is not itself a [`Session`]: it is a stateless adapter
13//! *around* a per-call [`LocalSession`]. Each call loads a `LocalSession`
14//! from a JSON save file, submits one request, and saves it back. This is
15//! what a headless CLI drives, one process invocation per request.
16//!
17//! A future `RemoteSession` would hold no authority at all, only a connection
18//! to a host reached over some transport. That, and any pluggable `Store`
19//! backend beyond the single JSON file [`FileSession`] ships, are deliberately
20//! deferred until a concrete consumer exists (see the workspace design notes).
21//!
22//! Redaction is automatic: a [`Request::Query`] runs [`turnbase::Game::view`]
23//! for the requesting seat first, so only that seat's view is ever produced,
24//! never the raw state with every seat's hidden information.
25
26mod file;
27mod local;
28
29pub use file::{Error, FileSession};
30pub use local::LocalSession;
31
32use turnbase::{Game, PlayerId};
33use turnbase_protocol::{Request, Response};
34
35/// A running game, reachable in-process or (later) over a transport.
36pub trait Session<G: Game> {
37 /// Applies `request` on behalf of `player` and returns the response.
38 fn submit(&mut self, player: PlayerId, request: Request<G::Action>) -> Response<G::View>;
39}